diff --git a/.gitignore b/.gitignore index 9e52038..ea2211f 100644 --- a/.gitignore +++ b/.gitignore @@ -15,7 +15,7 @@ a.out cmd/pcloudcc/build/pcloudcc **/*/.cache/ compile_commands.json - +compile_commands.events.json /cmd/pcloudcc/build/ /.cache/ /lib/poverlay_linux/overlay_client diff --git a/control_tools.cpp b/control_tools.cpp index 0612dcb..ff48196 100644 --- a/control_tools.cpp +++ b/control_tools.cpp @@ -41,7 +41,8 @@ #include "pclsync/overlay_client.h" #include "pclsync_lib.h" -#include "psynclib.h" +#include "pclsync/psynclib.h" +#include "pclsync/pshm.h" #include "CLI11.hpp" @@ -60,62 +61,10 @@ enum command_ids_ { STOPSYNC }; -std::pair split_paths(const std::string &input) { - std::string path1, path2; - bool in_quotes = false; - bool escaped = false; - std::string current_path; - - for (char c : input) { - if (escaped) { - current_path += c; - escaped = false; - } else if (c == '\\') { - escaped = true; - } else if (c == '"') { - in_quotes = !in_quotes; - current_path += c; - } else if (c == ' ' && !in_quotes) { - if (!current_path.empty()) { - if (path1.empty()) { - path1 = current_path; - } else { - path2 = current_path; - break; - } - current_path.clear(); - } - } else { - current_path += c; - } - } - - if (!current_path.empty()) { - if (path1.empty()) { - path1 = current_path; - } else if (path2.empty()) { - path2 = current_path; - } - } - - auto remove_quotes = [](std::string &s) { - if (s.size() >= 2 && s.front() == '"' && s.back() == '"') { - s = s.substr(1, s.size() - 2); - } - }; - - remove_quotes(path1); - remove_quotes(path2); - - return {path1, path2}; -} - int list_sync_folders() { int ret; char *errm; size_t errmsz; - void *rep; - size_t repsz; int result; psync_folder_list_t *flist; psync_folder_t *folder; @@ -123,51 +72,50 @@ int list_sync_folders() { errm = NULL; errmsz = 0; - rep = NULL; - repsz = 0; rval = 0; - result = SendCall(LISTSYNC, "", &ret, &errm, &errmsz, &rep, &repsz); + result = SendCall(LISTSYNC, "", &ret, &errm, &errmsz); if (result != 0) { std::cout << "List Sync Folders failed. return is " << ret << " and message is " << (errm ? errm : "no message") << std::endl; rval = result; - } else if (rep && repsz > 0) { - flist = static_cast(rep); + } - if (repsz < sizeof(psync_folder_list_t)) { - std::cout << "Error: Insufficient data for folder list structure" - << std::endl; - rval = -1; - } else { - - const int id_width = 12; - const int path_width = 30; + if(pshm_read((void**)&flist, NULL)) { + const int id_width = 12; + const int path_width = 30; + if(flist->foldercnt > 0) { std::cout << std::left << std::setw(id_width) << "Folder ID" << std::setw(path_width) << "Local Path" << std::setw(path_width) << "Remote Path" << std::endl; std::cout << std::string(id_width, '-') << std::string(path_width - 1, '-') << std::string(path_width - 1, '-') << std::endl; - for (uint32_t i = 0; i < flist->foldercnt; i++) { folder = &flist->folders[i]; std::cout << std::left << std::setw(id_width) << folder->folderid << std::setw(path_width) << folder->localpath << std::setw(path_width) << folder->remotepath << std::endl; } + } else { + std::cout << "No synchronized folders found." << std::endl; rval = ret; } - } else { - std::cout << "No synchronized folders found." << std::endl; rval = ret; + + free(flist); + } else { + std::cout << "failed to read folder list from shm" << std::endl; + return -1; + } + + if(errm) { + free(errm); } - free(errm); - free(rep); return rval; } @@ -176,7 +124,8 @@ int start_crypto(const char *pass) { char *errm; size_t errm_size; - int result = SendCall(STARTCRYPTO, pass, &ret, &errm, &errm_size, NULL, NULL); + int result = SendCall(STARTCRYPTO, pass, &ret, &errm, &errm_size); + if (result != 0 || ret != 0) { std::cout << "Start Crypto failed. return is " << ret << " and message is " << (errm ? errm : "no message") << std::endl; @@ -193,7 +142,7 @@ int stop_crypto() { char *errm; size_t errm_size; - int result = SendCall(STOPCRYPTO, "", &ret, &errm, &errm_size, NULL, NULL); + int result = SendCall(STOPCRYPTO, "", &ret, &errm, &errm_size); if (result != 0) { std::cout << "Stop Crypto failed. return is " << ret << " and message is " << (errm ? errm : "no message") << std::endl; @@ -217,7 +166,7 @@ int remove_sync_folder(const char *folderid) { errmsz = 0; rval = 0; - result = SendCall(STOPSYNC, folderid, &ret, &errm, &errmsz, NULL, NULL); + result = SendCall(STOPSYNC, folderid, &ret, &errm, &errmsz); if (result != 0) { std::cout << "Remove Sync Folder failed with unknown error. return is " << ret << " and message is " << (errm ? errm : "no message") @@ -227,7 +176,10 @@ int remove_sync_folder(const char *folderid) { std::cout << "Successfully removed sync folder with folderid " << folderid << std::endl; } - free(errm); + + if(errm) { + free(errm); + } return rval; } @@ -237,20 +189,15 @@ int add_sync_folder(std::string localpath, std::string remotepath) { int ret; char *errm; size_t errmsz; - void *rep; - size_t repsz; int result; int rval; errm = NULL; errmsz = 0; - rep = NULL; - repsz = 0; rval = 0; std::string combinedPaths = localpath + '|' + remotepath; - result = SendCall(ADDSYNC, combinedPaths.c_str(), &ret, &errm, &errmsz, &rep, - &repsz); + result = SendCall(ADDSYNC, combinedPaths.c_str(), &ret, &errm, &errmsz); if (result != 0) { if (result == -1) { @@ -262,22 +209,14 @@ int add_sync_folder(std::string localpath, std::string remotepath) { << std::endl; } rval = result; - } else if (rep && repsz > 0) { - if (repsz < sizeof(psync_syncid_t)) { - std::cout << "Error: Insufficient data for folder list structure" - << std::endl; - rval = -1; - } else { - rval = ret; - } } else { - std::cout << "Error: Did not get a syncid from add_sync_folder." - << std::endl; rval = ret; } - free(errm); - free(rep); + if(errm) { + free(errm); + } + return rval; } @@ -286,11 +225,12 @@ int finalize() { char *errm; size_t errm_size; - SendCall(FINALIZE, "", &ret, &errm, &errm_size, NULL, NULL); + SendCall(FINALIZE, "", &ret, &errm, &errm_size); std::cout << "Exiting ..." << std::endl; - if (errm) - free(errm); + if (errm){ + free(errm); + } return ret; } diff --git a/doc/request-response.org b/doc/request-response.org index 537f1fc..8967e0b 100644 --- a/doc/request-response.org +++ b/doc/request-response.org @@ -26,8 +26,7 @@ that gets created when the server is started. socket -> poverlay : request poverlay -> poverlay : poverlay_handle_request poverlay -> poverlay : poverlay_get_response - poverlay -> poverlay : serialize_response_message - poverlay -> socket : response (serialized) + poverlay -> socket : response socket -> overlay_client : read_response overlay_client -> control_tools : (msg, msgsz, payload, payloadsz) control_tools -> user : print results diff --git a/pclsync/overlay_client.c b/pclsync/overlay_client.c index 9ad75ce..47d69a3 100644 --- a/pclsync/overlay_client.c +++ b/pclsync/overlay_client.c @@ -62,7 +62,7 @@ #include "overlay_client.h" #include "poverlay_protocol.h" -#define POVERLAY_BUFSIZE 16 * 1024 +#define POVERLAY_BUFSIZE 512 // for easier error tracing... #define POVERLAY_SOCKET_CREATE_FAILED -100 @@ -73,106 +73,8 @@ #define POVERLAY_READ_INCOMPLETE -105 #define POVERLAY_READ_INVALID_RESPONSE -106 -response_message *deserialize_response_message(const char *buffer, - size_t buffer_size) { - if (buffer_size < 2 * sizeof(size_t) + sizeof(uint32_t) + sizeof(uint64_t)) { - debug(D_ERROR, "Buffer size too small: %zu", buffer_size); - return NULL; - } - - const char *ptr = buffer; - - // Allocate response_message - response_message *resp = (response_message *)malloc(sizeof(response_message)); - if (resp == NULL) { - debug(D_ERROR, "Failed to allocate response_message"); - return NULL; - } - - // Get message size - size_t msg_size = be64toh(*(size_t *)ptr); - ptr += sizeof(size_t); - - debug(D_ERROR, "Message size: %zu", msg_size); - - if (msg_size < sizeof(uint32_t) + sizeof(uint64_t)) { - debug(D_ERROR, "Invalid message size: %zu", msg_size); - free(resp); - return NULL; - } - - // Allocate message with extra space for the flexible array member - size_t alloc_size = - sizeof(message) + msg_size - sizeof(uint32_t) - sizeof(uint64_t); - resp->msg = (message *)malloc(alloc_size); - if (resp->msg == NULL) { - debug(D_ERROR, "Failed to allocate message"); - free(resp); - return NULL; - } - - resp->msg->type = ntohl(*(uint32_t *)ptr); - ptr += sizeof(uint32_t); - - resp->msg->length = be64toh(*(uint64_t *)ptr); - ptr += sizeof(uint64_t); - - debug(D_ERROR, "Message type: %u, length: %lu", resp->msg->type, - resp->msg->length); - - // Calculate the size of the value array - size_t value_size = msg_size - sizeof(uint32_t) - sizeof(uint64_t); - - if (value_size > 0) { - if (ptr + value_size > buffer + buffer_size) { - debug(D_ERROR, "Buffer overflow detected"); - free(resp->msg); - free(resp); - return NULL; - } - memcpy(resp->msg->value, ptr, value_size); - ptr += value_size; - } - - // Deserialize payload size - if (ptr + sizeof(size_t) > buffer + buffer_size) { - debug(D_ERROR, "Buffer overflow detected when reading payload size"); - free(resp->msg); - free(resp); - return NULL; - } - resp->payloadsz = be64toh(*(size_t *)ptr); - ptr += sizeof(size_t); - - debug(D_ERROR, "Payload size: %zu", resp->payloadsz); - - // Deserialize payload - if (resp->payloadsz > 0) { - if (ptr + resp->payloadsz > buffer + buffer_size) { - debug(D_ERROR, "Buffer overflow detected when reading payload"); - free(resp->msg); - free(resp); - return NULL; - } - resp->payload = malloc(resp->payloadsz); - if (resp->payload == NULL) { - debug(D_ERROR, "Failed to allocate payload"); - free(resp->msg); - free(resp); - return NULL; - } - memcpy(resp->payload, ptr, resp->payloadsz); - } else { - resp->payload = NULL; - } - - return resp; -} - -void free_response_message(response_message *resp) { +void free_response_message(message *resp) { if (resp) { - free(resp->msg); - free(resp->payload); free(resp); } } @@ -182,7 +84,7 @@ int QueryState(pCloud_FileState *state, char *path) { char *errm; size_t errm_size; - if (!SendCall(4, path /*IN*/, &rep, &errm, &errm_size, NULL, NULL)) { + if (!SendCall(4, path /*IN*/, &rep, &errm, &errm_size)) { debug(D_NOTICE, "QueryState responese rep[%d] path[%s]", rep, path); if (errm) debug(D_NOTICE, "The error is %s", errm); @@ -243,15 +145,15 @@ int write_request(int fd, int msgtype, const char *value, char **out, int size; char *buf; const char *err; - request_message *request; + message *request; char *curbuf; *ret = 0; // Initialize ret to 0 len = strlen(value); - size = sizeof(request_message) + len + 1; + size = sizeof(message) + len + 1; buf = (char *)malloc(size); - request = (request_message *)buf; + request = (message *)buf; memset(request, 0, size); request->type = msgtype; strncpy(request->value, value, len + 1); @@ -288,122 +190,53 @@ int write_request(int fd, int msgtype, const char *value, char **out, // write an error message OR an API response value to out (and its // size to out_size), a "ret" value to ret (redundant?), and the // callback's return data to payload and payloadsz. -int read_response(int fd, char **out, size_t *out_size, int *ret, - void **payload, size_t *payloadsz) { - char buffer[POVERLAY_BUFSIZE]; - ssize_t bytes_read = read(fd, buffer, POVERLAY_BUFSIZE); +int read_response(int fd, char **out, size_t *out_size, int *ret) { + message *msg; + ssize_t bytes_read; - if (bytes_read <= 0) { - const char *error_msg = - (bytes_read == 0) ? "Connection closed" : strerror(errno); - *out = strdup(error_msg); - *out_size = strlen(error_msg) + 1; - *ret = -1; - return -1; - } - - if (bytes_read < sizeof(response_message)) { - const char *error_msg = "Incomplete response"; - *out = strdup(error_msg); - *out_size = strlen(error_msg) + 1; - *ret = -1; - return -1; - } - - // response_message *resp = (response_message *)buffer; - response_message *resp = deserialize_response_message(buffer, bytes_read); - if (resp == NULL) { - const char *error_msg = "Failed to deserialize response"; - *out = strdup(error_msg); - *out_size = strlen(error_msg) + 1; - *ret = -1; - return -1; - } - - // Validate the response_message structure - if (resp->msg == NULL || - (size_t)bytes_read < sizeof(response_message) + sizeof(message) || - (size_t)bytes_read < sizeof(response_message) + resp->msg->length) { - const char *error_msg = "Invalid response structure"; - *out = strdup(error_msg); - *out_size = strlen(error_msg) + 1; - *ret = -1; - return -1; - } - - message *msg = resp->msg; - size_t value_size = msg->length - sizeof(message); - - // Validate message length - if (msg->length < sizeof(message) || - (size_t)bytes_read < sizeof(response_message) + msg->length) { - const char *error_msg = "Invalid message length"; - *out = strdup(error_msg); - *out_size = strlen(error_msg) + 1; - *ret = -1; - return -1; - } - - *out = malloc(value_size + 1); - if (*out == NULL) { - const char *error_msg = "Memory allocation failed"; - *out = strdup(error_msg); - *out_size = strlen(error_msg) + 1; - *ret = -1; - free_response_message(resp); - return -1; - } - - memcpy(*out, msg->value, value_size); - (*out)[value_size] = '\0'; - *out_size = value_size + 1; - - *ret = msg->type; - - if (payload != NULL && payloadsz != NULL) { - if (resp->payload != NULL && resp->payloadsz > 0) { - *payload = malloc(resp->payloadsz); - if (*payload == NULL) { - const char *error_msg = "Memory allocation failed for payload"; - free(*out); + msg = (message *)malloc(POVERLAY_BUFSIZE); + if (msg == NULL) { + const char *error_msg = "Memory allocation failed"; *out = strdup(error_msg); *out_size = strlen(error_msg) + 1; *ret = -1; - free_response_message(resp); return -1; - } - memcpy(*payload, resp->payload, resp->payloadsz); - *payloadsz = resp->payloadsz; - } else { - *payload = NULL; - *payloadsz = 0; } - } - free_response_message(resp); - return 0; + bytes_read = read(fd, msg, POVERLAY_BUFSIZE); + if (bytes_read <= 0) { + const char *error_msg = (bytes_read == 0) ? "Connection closed" : "Read error"; + free(msg); + *out = strdup(error_msg); + *out_size = strlen(error_msg) + 1; + *ret = -1; + return -1; + } + + *out = (char *)malloc(msg->length); + memcpy(*out, msg->value, msg->length); + *out_size = msg->length; + *ret = msg->type; + + free(msg); + return 0; } -int SendCall(int id /*IN*/, const char *path /*IN*/, int *ret /*OUT*/, - char **out /*OUT*/, size_t *out_size, void **reply_data, - size_t *reply_size) { +// path contains the input argument(s). +int SendCall(int id, const char *path, int *ret, char **errm, size_t *errmsz) { int result; int sockfd; sockfd = -1; result = 0; - *out = NULL; - *out_size = 0; + *errm = NULL; + *errmsz = 0; *ret = 0; - // side effects: modify out, out_size, ret - sockfd = socket_connect(POVERLAY_SOCK_PATH, out, out_size, ret); + sockfd = socket_connect(POVERLAY_SOCK_PATH, errm, errmsz, ret); if (sockfd >= 0) { - // side effects: modify out, out_size, ret - if ((result = write_request(sockfd, id, path, out, out_size, ret)) == 0) { - // side effects: modify out, out_size, ret, reply_data, reply_size - result = - read_response(sockfd, out, out_size, ret, reply_data, reply_size); + if ((result = write_request(sockfd, id, path, errm, errmsz, ret)) == 0) { + result = read_response(sockfd, errm, errmsz, ret); } close(sockfd); } else { diff --git a/pclsync/overlay_client.h b/pclsync/overlay_client.h index 96a6133..aa1d17e 100644 --- a/pclsync/overlay_client.h +++ b/pclsync/overlay_client.h @@ -48,11 +48,9 @@ typedef enum _pCloud_FileState { FileStateInvalid } pCloud_FileState; -int QueryState(pCloud_FileState *state /*OUT*/, char *path /*IN*/); +int QueryState(pCloud_FileState *, char *); +int SendCall(int id, const char *, int *, char **, size_t *); -int SendCall(int id /*IN*/, const char *path /*IN*/, int *ret /*OUT*/, - char **out /*OUT*/, size_t *out_size, void **reply_data, - size_t *reply_size); #ifdef __cplusplus } #endif diff --git a/pclsync/pfolder.c b/pclsync/pfolder.c index 95fa38b..88f689c 100644 --- a/pclsync/pfolder.c +++ b/pclsync/pfolder.c @@ -925,3 +925,4 @@ psync_folder_list_t *psync_list_get_list(char *syncTypes) { return ret; } + diff --git a/pclsync/poverlay.c b/pclsync/poverlay.c index c396b85..a288da7 100644 --- a/pclsync/poverlay.c +++ b/pclsync/poverlay.c @@ -55,47 +55,6 @@ int overlays_running = 1; int callbacks_running = 1; -// Serialization function -size_t serialize_response_message(const response_message *resp, - char **out_buffer) { - // Calculate total size needed - size_t msg_size = sizeof(uint32_t) + sizeof(uint64_t) + resp->msg->length; - size_t total_size = - sizeof(size_t) + msg_size + sizeof(size_t) + resp->payloadsz; - - // Allocate buffer - *out_buffer = (char *)malloc(total_size); - if (*out_buffer == NULL) - return 0; - - char *ptr = *out_buffer; - - // Serialize msg size - *(size_t *)ptr = htobe64(msg_size); - ptr += sizeof(size_t); - - // Serialize msg - *(uint32_t *)ptr = htonl(resp->msg->type); - ptr += sizeof(uint32_t); - - *(uint64_t *)ptr = htobe64(resp->msg->length); - ptr += sizeof(uint64_t); - - memcpy(ptr, resp->msg->value, resp->msg->length); - ptr += resp->msg->length; - - // Serialize payload size - *(size_t *)ptr = htobe64(resp->payloadsz); - ptr += sizeof(size_t); - - // Serialize payload - if (resp->payloadsz > 0 && resp->payload != NULL) { - memcpy(ptr, resp->payload, resp->payloadsz); - } - - return total_size; -} - void psync_overlay_main_loop() { struct sockaddr_un addr; int fd, cl; @@ -144,8 +103,8 @@ void psync_overlay_handle_request(void *lpvParam) { int readbytes; // total bytes read from request char rqbuf[POVERLAY_BUFSIZE]; // request buffer, contains the request message char *rqbufp; // request buffer ptr, for convenient iteration - request_message *request; // request message - response_message *response; // response message and payload + message *request; // request message + message *response; // response message and payload request = NULL; response = NULL; @@ -159,7 +118,7 @@ void psync_overlay_handle_request(void *lpvParam) { readbytes += rc; rqbufp = rqbufp + rc; if (readbytes > 12) { - request = (request_message *)rqbuf; + request = (message *)rqbuf; if (request->length == (uint64_t)readbytes) break; } @@ -172,50 +131,23 @@ void psync_overlay_handle_request(void *lpvParam) { goto cleanup; } - // allocate and initialize response message - response = (response_message *)psync_malloc(sizeof(response_message)); - memset(response, 0, sizeof(response_message)); - response->msg = NULL; - response->payload = NULL; - response->payloadsz = 0; - - // get the response for the request, and write the response to the - // sockfd. - request = (request_message *)rqbuf; + request = (message *)rqbuf; + response = (message *)malloc(POVERLAY_BUFSIZE); if (request) { psync_overlay_get_response(request, response); - char *rsbufp; - size_t bytes_written = 0; - size_t responsesz = serialize_response_message(response, &rsbufp); - if (responsesz <= 0) { - debug(D_ERROR, "failed to serialize response message"); - return; + ssize_t total_size = sizeof(uint32_t) + sizeof(uint64_t) + response->length; + ssize_t bytes_written = write(*sockfd, response, total_size); + + if (bytes_written == -1) { + debug(D_ERROR, "Failed to write to socket: %s", strerror(errno)); + return; + } else if (bytes_written < total_size) { + debug(D_ERROR, "Incomplete write to socket: wrote %zd of %zd bytes", bytes_written, total_size); + return; } - while (bytes_written < responsesz) { - ssize_t written = - write(*sockfd, rsbufp + bytes_written, responsesz - bytes_written); - if (written == -1) { - if (errno == EINTR) { - // Interrupted by signal, try again - continue; - } - debug(D_ERROR, "failed to write to socket: %s", strerror(errno)); - break; - } - bytes_written += written; - } - free(rsbufp); - if (bytes_written < responsesz) { - debug(D_ERROR, "failed to write entire message to socket"); - return; - } - - debug(D_NOTICE, - "Successfully sent full reply: %zu bytes structure, %zu bytes " - "additional data", - response->msg->length, response->payloadsz); + debug(D_NOTICE, "Successfully wrote %zd bytes to socket", bytes_written); } else { debug(D_ERROR, "No valid request received"); } @@ -225,12 +157,6 @@ cleanup: close(*sockfd); } if (response) { - if (response->msg) { - psync_free(response->msg); - } - if (response->payload) { - psync_free(response->payload); - } psync_free(response); } @@ -264,8 +190,8 @@ void psync_overlay_init_callbacks() { memset(callbacks, 0, sizeof(poverlay_callback) * callbacks_size); } -static void psync_overlay_get_status_response(request_message *request, - response_message *response, +static void psync_overlay_get_status_response(message *request, + message *response, size_t available_space) { psync_path_status_t stat; @@ -276,56 +202,24 @@ static void psync_overlay_get_status_response(request_message *request, } switch (psync_path_status_get_status(stat)) { case PSYNC_PATH_STATUS_IN_SYNC: - response->msg->type = 10; + response->type = 10; break; case PSYNC_PATH_STATUS_IN_PROG: - response->msg->type = 12; + response->type = 12; break; case PSYNC_PATH_STATUS_PAUSED: case PSYNC_PATH_STATUS_REMOTE_FULL: case PSYNC_PATH_STATUS_LOCAL_FULL: - response->msg->type = 11; + response->type = 11; break; default: - response->msg->type = 13; - snprintf(response->msg->value, available_space, "No."); + response->type = 13; + snprintf(response->value, available_space, "No."); } } -static void -psync_overlay_get_overlay_response_payload(request_message *request, - response_message *response) { - if (!response->payload) { - response->payloadsz = 0; - debug(D_NOTICE, "Callback succeeded with no reply data"); - return; - } - - if (request->type == 23) { - // LISTSYNC - psync_folder_list_t *folders = (psync_folder_list_t *)response->payload; - response->payloadsz = sizeof(psync_folder_list_t) + - folders->foldercnt * sizeof(psync_folder_t); - } else if (request->type == 24) { - // ADDSYNC - response->payloadsz = sizeof(psync_syncid_t); - } else { - // default: response has no payload - response->payloadsz = 0; - } - - if (response->payload == NULL) { - response->payloadsz = 0; - debug(D_NOTICE, "No reply data received"); - return; - } - - debug(D_NOTICE, "Callback succeeded with reply data, length: %zu", - response->payloadsz); -} - -static void psync_overlay_get_overlay_response(request_message *request, - response_message *response, +static void psync_overlay_get_overlay_response(message *request, + message *response, size_t available_space) { int cbidx; // callback index (based on message type) int cbret; // callback return value @@ -335,44 +229,40 @@ static void psync_overlay_get_overlay_response(request_message *request, if (!callbacks_running || (request->type >= ((uint32_t)calbacks_lower_band + (uint32_t)callbacks_size))) { - response->msg->type = 13; - snprintf(response->msg->value, available_space, "Invalid type."); + response->type = 13; + snprintf(response->value, available_space, "Invalid type."); debug(D_NOTICE, "Invalid request type: %u", request->type); return; } if (!callbacks[cbidx]) { - response->msg->type = 13; - snprintf(response->msg->value, available_space, + response->type = 13; + snprintf(response->value, available_space, "No callback with this id registered."); debug(D_NOTICE, "No callback registered for type: %u", request->type); return; } - cbret = callbacks[cbidx](request->value, &response->payload); + cbret = callbacks[cbidx](request->value); if (cbret == 0) { - response->msg->type = 0; - psync_overlay_get_overlay_response_payload(request, response); + response->type = 0; } else { - response->msg->type = cbret; - snprintf(response->msg->value, available_space, + response->type = cbret; + snprintf(response->value, available_space, "Callback returned error code."); debug(D_NOTICE, "Callback failed with return code: %d", cbret); } } -void psync_overlay_get_response(request_message *request, - response_message *response) { +void psync_overlay_get_response(message *request, + message *response) { const char *dbgmsg; // debug messages size_t value_avail; // space available to store value (flexible array) dbgmsg = NULL; - response->msg = (message *)psync_malloc(POVERLAY_BUFSIZE); - memset(response->msg, 0, POVERLAY_BUFSIZE); - response->msg->length = 0; - response->payload = NULL; - response->payloadsz = 0; + memset(response, 0, POVERLAY_BUFSIZE); + response->length = 0; value_avail = POVERLAY_BUFSIZE - sizeof(message); // never print the crypto password to the logs in plain text @@ -388,21 +278,21 @@ void psync_overlay_get_response(request_message *request, // a message with a type != 13 and a null string value after // processing is considered successful. set value to "Ok." - if (response->msg->type != 13 && response->msg->value[0] == '\0') { - snprintf(response->msg->value, value_avail, "Ok."); + if (response->type != 13 && response->value[0] == '\0') { + snprintf(response->value, value_avail, "Ok."); } else { debug(D_WARNING, "not updating value to Ok: response->msg->type=%d, " "response->msg->value=%s", - response->msg->type, response->msg->value); + response->type, response->value); } // truncate messages that exceed the buffer boundaries - size_t value_length = strnlen(response->msg->value, value_avail); - response->msg->length = sizeof(message) + value_length + 1; - if (response->msg->length > POVERLAY_BUFSIZE) { - response->msg->length = POVERLAY_BUFSIZE; - response->msg->value[value_avail - 1] = '\0'; + size_t value_length = strnlen(response->value, value_avail); + response->length = sizeof(message) + value_length + 1; + if (response->length > POVERLAY_BUFSIZE) { + response->length = POVERLAY_BUFSIZE; + response->value[value_avail - 1] = '\0'; debug(D_WARNING, "Response message truncated to fit buffer"); } } diff --git a/pclsync/poverlay.h b/pclsync/poverlay.h index 0884153..e278e5e 100644 --- a/pclsync/poverlay.h +++ b/pclsync/poverlay.h @@ -49,8 +49,7 @@ extern int callbacks_running; void psync_overlay_main_loop(VOID); void psync_overlay_handle_request(LPVOID); -void psync_overlay_get_response(request_message *rq /*IN*/, - response_message *rs /*OUT*/); +void psync_overlay_get_response(message*, message*); void psync_overlay_stop_overlays(); void psync_overlay_start_overlays(); void psync_overlay_stop_overlay_callbacks(); @@ -59,6 +58,6 @@ int psync_overlay_overlays_running(); int psync_overlay_callbacks_running(); void psync_overlay_init_callbacks(); -int psync_overlay_register_callback(int id, poverlay_callback callback); +int psync_overlay_register_callback(int, poverlay_callback); #endif // POVERLAY_H diff --git a/pclsync/poverlay_protocol.h b/pclsync/poverlay_protocol.h index 0d5234e..45dd782 100644 --- a/pclsync/poverlay_protocol.h +++ b/pclsync/poverlay_protocol.h @@ -10,22 +10,10 @@ #define POVERLAY_SOCK_PATH "/tmp/pcloud_unix_soc.sock" #endif - typedef struct _message { uint32_t type; uint64_t length; char value[]; } message; -// represents a request message -typedef message request_message; - -// represents a response message; this includes the API response -// message and any payload data returned by the callback function. -typedef struct { - void *payload; // data returned by the callback function - size_t payloadsz; // size of payload - message *msg; // API response message -} response_message; - #endif \ No newline at end of file diff --git a/pclsync/pshm.c b/pclsync/pshm.c new file mode 100644 index 0000000..f720b58 --- /dev/null +++ b/pclsync/pshm.c @@ -0,0 +1,129 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "debug.h" + +#include "pshm.h" + +key_t pshm_get_key() { + char path[PATH_MAX]; + char *home; + + home = getenv("HOME"); + if (home == NULL) { + debug(D_ERROR, "HOME environment variable is not set"); + return (key_t)-1; + } + snprintf(path, sizeof(path), "%s/.pcloud/data.db", home); + + return ftok(path, 'A'); +} + +int pshm_getid() { + key_t key; + + key = pshm_get_key(); + if(key == -1) { + debug(D_ERROR, "failed to get ipc key"); + return -1; + } + + return shmget(key, PSYNC_SHM_SIZE, IPC_CREAT | 0666); +} + +bool pshm_read(void **data, size_t *datasz) { + int shmid; + psync_shm *shm; + int flag; + char *dataArea; + + shmid = pshm_getid(); + if (shmid == -1) { + debug(D_ERROR, "Failed to get shared memory ID"); + return false; + } + + shm = (psync_shm*)shmat(shmid, NULL, 0); + if (shm == (void*)-1) { + debug(D_ERROR, "Failed to attach to shared memory: %s", strerror(errno)); + return false; + } + + __atomic_load(&shm->flag, &flag, __ATOMIC_SEQ_CST); + if(flag != 1) { + shmdt(shm); + return false; + } + + if(datasz != NULL) { + *datasz = shm->datasz; + } + + *data = malloc(shm->datasz); + if(*data == NULL) { + debug(D_ERROR, "Failed to allocate memory for shared data"); + shmdt(shm); + return false; + } + + dataArea = (char *)shm + sizeof(psync_shm); + memcpy(*data, dataArea, shm->datasz); + + __atomic_store_n(&shm->flag, 0, __ATOMIC_SEQ_CST); + + shmdt(shm); + return true; +} + +void pshm_write(const void *data, size_t datasz) { + int shmid; + psync_shm* shm; + char *dataArea; + + if (datasz > PSYNC_SHM_SIZE - sizeof(psync_shm)) { + debug(D_ERROR, "Data size exceeds available shared memory size"); + return; + } + + shmid = pshm_getid(); + if (shmid == -1) { + debug(D_ERROR, "Failed to get shared memory ID"); + return; + } + + shm = (psync_shm*)shmat(shmid, NULL, 0); + if (shm == (void*)-1) { + debug(D_ERROR, "Failed to attach to shared memory: %s", strerror(errno)); + return; + } + + if (shm->flag == 0 && shm->datasz == 0) { + debug(D_NOTICE, "Initializing shared memory segment"); + // Clear the structure first + memset(shm, 0, sizeof(psync_shm)); + // Data area starts right after the structure + shm->data = (char *)shm + sizeof(psync_shm); + shm->datasz = 0; + shm->flag = 0; + } + + dataArea = (char *)shm + sizeof(psync_shm); + memcpy(dataArea, data, datasz); + + shm->datasz = datasz; + __atomic_store_n(&shm->flag, 1, __ATOMIC_SEQ_CST); + + if (shmdt(shm) == -1) { + debug(D_ERROR, "Failed to detach from shared memory: %s", strerror(errno)); + } +} + +int pshm_cleanup() { + return shmctl(pshm_getid(), IPC_RMID, NULL); +} \ No newline at end of file diff --git a/pclsync/pshm.h b/pclsync/pshm.h new file mode 100644 index 0000000..f3719eb --- /dev/null +++ b/pclsync/pshm.h @@ -0,0 +1,33 @@ +#ifndef __PSHM_H + +#define __PSHM_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + +#define PSYNC_SHM_SIZE 4096 + +// shm is used to get the return values from the underlying pcloud functions +// called by the overlay client. this is needed for cases such as +// list_sync_folders, where the result should be presented to the user in the +// CLI. +typedef struct _psync_shm { + void *data; // overlay callback return value + size_t datasz; // overlay return value size + volatile int flag; // new data available +} psync_shm; + +void pshm_write(const void *data, size_t datasz); +bool pshm_read(void **data, size_t *datasz); +int pshm_cleanup(); + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/pclsync/psynclib.c b/pclsync/psynclib.c index 9ac7965..f571e41 100644 --- a/pclsync/psynclib.c +++ b/pclsync/psynclib.c @@ -71,6 +71,7 @@ #include "ppathstatus.h" #include "pscanner.h" #include "psettings.h" +#include "pshm.h" #include "pssl.h" #include "pstatus.h" #include "psyncer.h" @@ -355,6 +356,9 @@ uint32_t psync_download_state() { return 0; } void psync_destroy() { psync_do_run = 0; + if (pshm_cleanup() == -1) { + debug(D_ERROR, "failed to cleanup shm"); + } psync_fs_stop(); psync_terminate_status_waiters(); psync_send_status_update(); diff --git a/pclsync/psynclib.h b/pclsync/psynclib.h index c6f4771..c77b950 100644 --- a/pclsync/psynclib.h +++ b/pclsync/psynclib.h @@ -1809,7 +1809,7 @@ void psync_get_folder_ownerid(psync_folderid_t folderid, // void** pointer is null, then do not write any data back out for // the client. // -typedef int (*poverlay_callback)(const char *, void **); +typedef int (*poverlay_callback)(const char *); /* Registers file manager extension callback that will be called when packet * with id equals to the give one had arrived from extension. The id must be diff --git a/pclsync_lib.cpp b/pclsync_lib.cpp index 9da48f3..3972041 100644 --- a/pclsync_lib.cpp +++ b/pclsync_lib.cpp @@ -41,12 +41,15 @@ #include "poverlay.h" #include "psynclib.h" +#include "pshm.h" #include "pclsync_lib.h" namespace cc = console_client; namespace clib = cc::clibrary; +static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER; + static const std::string client_name = "pCloud CC v3.0.0"; clib::pclsync_lib::pclsync_lib() @@ -331,16 +334,13 @@ static void status_change(pstatus_t *status) { psync_free(err); } -int clib::pclsync_lib::start_crypto(const char *pass, void **payload) { - (void)payload; - +int clib::pclsync_lib::start_crypto(const char *pass) { std::cout << "calling startcrypto pass: " << pass << std::endl; get_lib().crypto_pass_ = pass; return lib_setup_cripto(); } -int clib::pclsync_lib::stop_crypto(const char *path, void **payload) { - (void)payload; +int clib::pclsync_lib::stop_crypto(const char *path) { (void)path; psync_crypto_stop(); @@ -348,20 +348,15 @@ int clib::pclsync_lib::stop_crypto(const char *path, void **payload) { return 0; } -int clib::pclsync_lib::finalize(const char *path, void **payload) { - (void)payload; +int clib::pclsync_lib::finalize(const char *path) { (void)path; psync_destroy(); exit(0); } -int clib::pclsync_lib::add_sync_folder(const char *path, void **payload) { - if (payload == nullptr) { - std::cerr << "Error: payload pointer is null" << std::endl; - return -255; - } - +// path is the local and remote path delimited by '|' +int clib::pclsync_lib::add_sync_folder(const char *path) { if (path == nullptr) { std::cerr << "Error: path is nullptr" << std::endl; return -255; @@ -377,53 +372,48 @@ int clib::pclsync_lib::add_sync_folder(const char *path, void **payload) { std::string localpath = combined.substr(0, delimiter_pos); std::string remotepath = combined.substr(delimiter_pos + 1); + psync_syncid_t syncid = psync_add_sync_by_path(localpath.c_str(), remotepath.c_str(), PSYNC_FULL); - psync_syncid_t syncid = - psync_add_sync_by_path(localpath.c_str(), remotepath.c_str(), PSYNC_FULL); - - uint64_t *payload_ptr = - static_cast(psync_malloc(sizeof(uint64_t))); - if (payload_ptr == nullptr) { - std::cerr << "Error: Failed to allocate memory for payload" << std::endl; - return -255; - } - + pthread_mutex_lock(&mtx); if (syncid == PSYNC_INVALID_SYNCID) { - std::cerr << "psync_add_sync_by_path returned PSYNC_INVALID_SYNCID" - << std::endl; - *payload_ptr = (static_cast(1) << 32) | - static_cast(PSYNC_INVALID_SYNCID); - return -1; - } else { - *payload_ptr = static_cast(syncid); + std::cerr << "psync_add_sync_by_path returned PSYNC_INVALID_SYNCID" << std::endl; + uint64_t error_value = (static_cast(1) << 32) | PSYNC_INVALID_SYNCID; + pshm_write(&error_value, sizeof(uint64_t)); + pthread_mutex_unlock(&mtx); + return -1; } - *payload = payload_ptr; + pshm_write(&syncid, sizeof(psync_syncid_t)); + pthread_mutex_unlock(&mtx); return 0; } -int clib::pclsync_lib::remove_sync_folder(const char *path, void **payload) { - (void)payload; +// path is the folderid to remove +int clib::pclsync_lib::remove_sync_folder(const char *path) { psync_folderid_t folderid; folderid = static_cast(std::stoull(path, nullptr, 10)); return psync_delete_sync_by_folderid(folderid); } -int clib::pclsync_lib::list_sync_folders(const char *path, void **payload) { +// path is not used +int clib::pclsync_lib::list_sync_folders(const char *path) { (void)path; - psync_folder_list_t *folders = psync_get_sync_list(); + psync_folder_list_t *folders; + size_t folderssz; + + folders = psync_get_sync_list(); if (!folders) { return -1; } - size_t alloc_size = - sizeof(*folders) + folders->foldercnt * sizeof(psync_folder_t); - *payload = psync_malloc(alloc_size); - if (*payload == NULL) { - psync_free(folders); - return -1; - } - memcpy(*payload, folders, alloc_size); + folderssz = + sizeof(psync_folder_list_t) + (folders->foldercnt * sizeof(psync_folder_t)); + + pthread_mutex_lock(&mtx); + pshm_write(folders, folderssz); + pthread_mutex_unlock(&mtx); + psync_free(folders); + return 0; } diff --git a/pclsync_lib.h b/pclsync_lib.h index 4c09f72..6b3cb08 100644 --- a/pclsync_lib.h +++ b/pclsync_lib.h @@ -29,12 +29,13 @@ /* Dependencies: - - - pclsync_lib_c.h */ #ifndef PCLSYNC_LIB_H #define PCLSYNC_LIB_H +#include + struct pstatus_struct_; typedef void (*status_callback_t)(int status, const char *stat_string); @@ -88,12 +89,12 @@ public: int init(); // std::string& username, std::string& password, std::string* // crypto_pass, int setup_crypto = 1, int usesrypto_userpass = 0); - static int start_crypto(const char *pass, void **rep); - static int stop_crypto(const char *path, void **rep); - static int finalize(const char *path, void **rep); - static int list_sync_folders(const char *path, void **rep); - static int add_sync_folder(const char *path, void **rep); - static int remove_sync_folder(const char *path, void **rep); + static int start_crypto(const char *pass); + static int stop_crypto(const char *path); + static int finalize(const char *path); + static int list_sync_folders(const char *path); + static int add_sync_folder(const char *path); + static int remove_sync_folder(const char *path); char *get_token(); int logout(); @@ -107,6 +108,7 @@ private: std::string crypto_pass_; std::string mount_; + bool to_set_mount_; bool daemon_;