#include #include #include #include #include #include #include #include #include #include bool msPacketSaveRequestGet(const struct msPacket *packet, int clientFd, struct msClientConnectionData *const data) { bool result = false; struct msPacketSaveRequest *self = NULL; uint64_t identifier = 0; FILE *fp = fmemopen(packet->rawData, packet->size, "r"); if (1 != fread(&identifier, sizeof identifier, 1, fp)) { goto return_ms_packet_save_request_get; } identifier = be64toh(identifier); self = malloc(sizeof *self); self->identifier = identifier; result = true; return_ms_packet_save_request_get: fclose(fp); if (!result) { return false; } return msPacketSaveRequestHandle(packet, self, data); } struct msPacketSaveRequestData { uint64_t identifier; }; static struct msPacketSaveRequestData * msPacketSaveRequestDataNew(uint64_t identifier) { struct msPacketSaveRequestData *self = malloc(sizeof *self); self->identifier = identifier; return self; } void msPacketSaveRequestDestroy(struct msPacketSaveRequest **self) { free(*self); *self = NULL; } void msPacketSaveRequestDataDestroy(struct msPacketSaveRequestData **self) { free(*self); *self = NULL; } static void shrinkOrNullSaveRequestsDataArray(struct msClientConnectionData *data) { size_t requestsLen = data->saveRequestsLen; struct msPacketSaveRequestData **requests = data->saveRequests; for (size_t i = 1; i < requestsLen; i++) { requests[i-1] = requests[i]; } requestsLen--; data->saveRequestsLen = requestsLen; if (!requestsLen) { free(data->saveRequests); data->saveRequests = NULL; return; } data->saveRequests = realloc(requests, sizeof *requests * requestsLen); } static unsigned char * vFileToBytes(struct VFile *file, size_t *len) { unsigned char *result = NULL; const ssize_t bufferLen = 120; ssize_t readLen = 0; unsigned char buffer[bufferLen]; if (!len) { goto return_vfile_to_bytes; } *len = 0; file->seek(file, 0, SEEK_SET); while ((readLen = file->read(file, buffer, bufferLen)) && readLen) { *len += readLen; size_t size = sizeof *result * *len; result = realloc(result, size); // memcpy_s not available in linux. memcpy(&result[*len - readLen], buffer, readLen); // NOLINT } return_vfile_to_bytes: return result; } static void msPacketSaveRequestSendResponse(struct mCoreThread *threadContext) { struct msClientConnectionData *data = (struct msClientConnectionData *) threadContext->userData; struct msPacketSaveRequestData **requests = data->saveRequests; size_t requestsLen; struct msPacketSaveRequestData *request = NULL; struct VFile *saveState = NULL; size_t saveLen = 0; unsigned char *save = NULL; struct msPacketSaveResponse *response = NULL; size_t rawDataLen = 0; unsigned char *rawData = NULL; struct msPacket *packet = NULL; pthread_mutex_lock(data->mutexSaveRequests); requestsLen = data->saveRequestsLen; if (!requestsLen) { printf("Somehow the queue of saveRequests got exhausted, this should not happen.\n"); goto unlock_ms_packet_save_request_send_response; } struct msCoreController *coreController = data->coreController; struct mCore *core = coreController->threadContext.core; request = requests[0]; shrinkOrNullSaveRequestsDataArray(data); unlock_ms_packet_save_request_send_response: pthread_mutex_unlock(data->mutexSaveRequests); if (!requestsLen) { return; } saveState = VFileMemChunk (NULL, 0); mCoreSaveStateNamed(core, saveState, SAVESTATE_ALL); save = vFileToBytes(saveState, &saveLen); response = msPacketSaveResponseNew(request->identifier, saveLen, save); rawData = msPacketSaveResponseSerialize(response, &rawDataLen); if (!rawData) { goto return_ms_packet_save_request_send_response; } packet = msPacketNew(PACKET_SEND_SAVE_RESPONSE, rawDataLen, rawData); msPacketSend(packet, data); return_ms_packet_save_request_send_response: if (!packet && rawData) { free(rawData); } if (response) { msPacketSaveResponseDestroy(&response); } if (request) { msPacketSaveRequestDataDestroy(&request); } if (packet) { msPacketDestroy(&packet); } } bool msPacketSaveRequestHandle(const struct msPacket *packet, struct msPacketSaveRequest *self, struct msClientConnectionData *const data) { bool result = false; struct msCoreController *coreController = data->coreController; size_t saveRequestsLen = 0; if (!coreController) { goto return_ms_packet_save_request_handle; } pthread_mutex_lock(data->mutexSaveRequests); data->saveRequestsLen++; saveRequestsLen = data->saveRequestsLen; // W: Suspicious usage of 'sizeof(A*)'; pointer to aggregate by clang-tidy. data->saveRequests = realloc(data->saveRequests, sizeof *data->saveRequests * saveRequestsLen); data->saveRequests[data->saveRequestsLen - 1] = msPacketSaveRequestDataNew(self->identifier); pthread_mutex_unlock(data->mutexSaveRequests); mCoreThreadRunFunction(&coreController->threadContext, &msPacketSaveRequestSendResponse); result = true; return_ms_packet_save_request_handle: msPacketSaveRequestDestroy(&self); return result; }