diff --git a/include/msgba/client_connection_data.h b/include/msgba/client_connection_data.h index f055ca6..f497447 100644 --- a/include/msgba/client_connection_data.h +++ b/include/msgba/client_connection_data.h @@ -7,6 +7,7 @@ #include struct msCoreController; +struct msPacketSaveRequestData; /** * Struct representing everything needed while a connection is established. @@ -24,6 +25,12 @@ struct msClientConnectionData { pthread_mutex_t *mutexPressKey; //! The last time we sent a frame. struct timespec *lastFrameDate; + //! The array of pending msPacketSaveRequest + struct msPacketSaveRequestData **saveRequests; + //! The mutex to take saveRequests from the beggining. + pthread_mutex_t *mutexSaveRequests; + //! The number of save requests. + size_t saveRequestsLen; }; /** diff --git a/include/msgba/core_controller.h b/include/msgba/core_controller.h index 2515c29..894732d 100644 --- a/include/msgba/core_controller.h +++ b/include/msgba/core_controller.h @@ -1,9 +1,10 @@ #ifndef MS_CORE_CONTROLLER #define MS_CORE_CONTROLLER #include +#include -#include #include +typedef uint32_t color_t; #include diff --git a/include/msgba/packet.h b/include/msgba/packet.h index e5f26f2..c3ea909 100644 --- a/include/msgba/packet.h +++ b/include/msgba/packet.h @@ -9,10 +9,18 @@ * The possible values for a packet id. */ enum { - PACKET_GET_HELLO, //! Packet id for get hello. - PACKET_SEND_FRAME, //! Packet id for send frame. - PACKET_GET_KEY_DOWN, //! Packet id for pressing a key. - PACKETS_NUMBER //! The number of recognized packets. + //! Packet id for get hello. + PACKET_GET_HELLO, + //! Packet id for send frame. + PACKET_SEND_FRAME, + //! Packet id for pressing a key. + PACKET_GET_KEY_DOWN, + //! Packet id for requesting a save to the server. + PACKET_GET_SAVE_REQUEST, + //! Packet id for sending a save to the client. + PACKET_SEND_SAVE_RESPONSE, + //! The number of recognized packets. + PACKETS_NUMBER }; /** @@ -24,20 +32,20 @@ struct msPacket { //! The size of the data contained in the packet. size_t size; //! The data as a byte array. (Not null terminated.) - unsigned char *raw_data; + unsigned char *rawData; }; /** * Asks the code to handle a concrete packet comming from a client. */ bool -msPacketHandle(struct msPacket *packet, int client_fd, struct msClientConnectionData *const data); +msPacketHandle(struct msPacket *packet, int clientFd, struct msClientConnectionData *const data); /** * Creates a new packet object. */ struct msPacket * -msPacketNew(const size_t id, const size_t size, unsigned char *raw_data); +msPacketNew(const size_t id, const size_t size, unsigned char *rawData); /** * Sends the packet to the client. @@ -56,4 +64,4 @@ msPacketDestroy(struct msPacket **packet); * Blocks the current thread. */ struct msPacket * -msPacketRead(int client_fd); +msPacketRead(int clientFd); diff --git a/include/msgba/packet/save_request.h b/include/msgba/packet/save_request.h new file mode 100644 index 0000000..ebc284a --- /dev/null +++ b/include/msgba/packet/save_request.h @@ -0,0 +1,56 @@ +#ifndef MS_PACKET_SAVE_REQUEST +#define MS_PACKET_SAVE_REQUEST +#include +#include +#include +#include +#include +#include +#include + +#include + +struct msPacket; +struct msPacketSaveRequestData; + +/** + * The packet kind received when the client wants a savestate. + */ +struct msPacketSaveRequest { + //! The unique for the client identifier for handling its response. + uint64_t identifier; +}; + +/** + * Destroys the msPacketSaveRequest + * @param selfPtr The pointer to the pointer to msPacketSaveRequest to null it after this operation. + */ +void +msPacketSaveRequestDestroy(struct msPacketSaveRequest **selfPtr); + +/** + * Handles the msPacketSaveRequest + * @param packet The packet containing msPacketSaveRequest, should have PACKET_GET_SAVE_REQUEST as its id. + * @param self This object. + * @param data The session data. + */ +bool +msPacketSaveRequestHandle(const struct msPacket *packet, struct msPacketSaveRequest *self, + struct msClientConnectionData *const data); + +/** + * Retrieves the msPacketSaveRequest contained in the packet rawData. + * @param packet The packet containing msPacketSaveRequest, should have PACKET_GET_SAVE_REQUEST as its id. + * @param clientFd The source of this packet. + * @param data The session data. + */ +bool +msPacketSaveRequestGet(const struct msPacket *packet, int clientFd, + struct msClientConnectionData *const data); +/** + * Destroys the struct msPacketSaveRequestData. + * @param selfPtr A pointer to a pointer to this object. + */ +void +msPacketSaveRequestDataDestroy(struct msPacketSaveRequestData **selfPtr); +#endif diff --git a/include/msgba/packet/save_response.h b/include/msgba/packet/save_response.h new file mode 100644 index 0000000..a3f5133 --- /dev/null +++ b/include/msgba/packet/save_response.h @@ -0,0 +1,43 @@ +#ifndef MS_PACKET_SAVE_RESPONSE +#define MS_PACKET_SAVE_RESPONSE + +#include +#include + +struct msPacket; + +/** + * Structure representing a save response response. + */ +struct msPacketSaveResponse { + //! The identifier of the request packet so the client nows that this is the response to that packet. + uint64_t identifier; + //! The length in bytes of the next field. + size_t saveLen; + //! The savestate content. + unsigned char *save; +}; + +/** + * Ends the life in memory of the send_frame packet. + * @param selfPtr A pointer to a pointer to this object. + */ +void +msPacketSaveResponseDestroy(struct msPacketSaveResponse **selfPtr); + +/** + * Creates a new save response packet. + * @param identifier Who this packet responses. + * @param saveLen The size of the save in bytes. + * @param save The bytes representing the savestate. + */ +struct msPacketSaveResponse * +msPacketSaveResponseNew(uint64_t identifier, size_t saveLen, unsigned char *save); +/** + * Converts this object to byte array. + * @param self This object. + * @param len (Output) A pointer to a number containing the resulting size in bytes. + */ +unsigned char * +msPacketSaveResponseSerialize(struct msPacketSaveResponse *const self, size_t *len); +#endif diff --git a/include/msgba/packet/send_frame.h b/include/msgba/packet/send_frame.h index 0bc83b7..9dd19bb 100644 --- a/include/msgba/packet/send_frame.h +++ b/include/msgba/packet/send_frame.h @@ -1,8 +1,9 @@ -#ifndef MS_PACKET_SEND_HELLO -#define MS_PACKET_SEND_HELLO -#include +#ifndef MS_PACKET_SEND_FRAME +#define MS_PACKET_SEND_FRAME +#include #include struct msPacket; +typedef uint32_t color_t; /** * Structure representing a video frame packet. diff --git a/include/msgba/player.h b/include/msgba/player.h index 5f9e2d5..2a6ec8f 100644 --- a/include/msgba/player.h +++ b/include/msgba/player.h @@ -1,5 +1,6 @@ #ifndef MS_PLAYER #define MS_PLAYER +#include #include #include #include diff --git a/meson.build b/meson.build index bef275e..b145071 100644 --- a/meson.build +++ b/meson.build @@ -1,4 +1,5 @@ project('tech.owlcode.msgba', 'c') +add_global_arguments('-std=c11', '-D_DEFAULT_SOURCE', language : 'c') inc = include_directories('include') @@ -11,6 +12,8 @@ sources = [ 'src/packet/hello.c', 'src/packet/send_frame.c', 'src/packet/key_down.c', + 'src/packet/save_request.c', + 'src/packet/save_response.c', 'src/client_connection_data.c', ] @@ -19,7 +22,8 @@ inc = [ ] link_arguments = [ - '-lmgba' + '-lmgba', + '-lpthread' ] executable('msgba', diff --git a/src/client_connection_data.c b/src/client_connection_data.c index 476cd81..f33b8af 100644 --- a/src/client_connection_data.c +++ b/src/client_connection_data.c @@ -2,6 +2,7 @@ #include #include +#include struct msClientConnectionData * msClientConnectionDataNew(size_t numberOfThread, int clientFd) { @@ -11,9 +12,13 @@ msClientConnectionDataNew(size_t numberOfThread, int clientFd) { data->coreController = NULL; data->mutexSendPacket = malloc(sizeof *data->mutexSendPacket); data->mutexPressKey = malloc(sizeof *data->mutexPressKey); + data->mutexSaveRequests = malloc(sizeof *data->mutexSaveRequests); + data->saveRequests = NULL; + data->saveRequestsLen = 0; data->lastFrameDate = calloc(sizeof *data->lastFrameDate, 1); pthread_mutex_init(data->mutexSendPacket, NULL); pthread_mutex_init(data->mutexPressKey, NULL); + pthread_mutex_init(data->mutexSaveRequests, NULL); return data; } @@ -24,10 +29,19 @@ msClientConnectionDataDestroy(struct msClientConnectionData **data) { } pthread_mutex_destroy((*data)->mutexSendPacket); pthread_mutex_destroy((*data)->mutexPressKey); + pthread_mutex_destroy((*data)->mutexSaveRequests); free((*data)->mutexSendPacket); free((*data)->mutexPressKey); + free((*data)->mutexSaveRequests); + if ((*data)->saveRequests) { + for (size_t i = 0; i<(*data)->saveRequestsLen; i++) { + msPacketSaveRequestDataDestroy(&(*data)->saveRequests[i]); + } + free((*data)->saveRequests); + } (*data)->mutexSendPacket = NULL; (*data)->mutexPressKey = NULL; + (*data)->mutexSaveRequests = NULL; free(*data); *data = NULL; } diff --git a/src/core_controller.c b/src/core_controller.c index d3d204e..5d3fbf4 100644 --- a/src/core_controller.c +++ b/src/core_controller.c @@ -1,3 +1,5 @@ +#include + #include #include #include @@ -85,7 +87,7 @@ mCoreThreadAfterStart(struct mCoreThread *threadContext) { struct msClientConnectionData *data = (struct msClientConnectionData *)threadContext->userData; struct msCoreController *coreController = data->coreController; struct mCore *core = coreController->threadContext.core; - if (!mCoreLoadStateNamed (core, coreController->saveState, 0)) { // SAVESTATE_SAVEDATA & SAVESTATE_RTC)) { + if (!mCoreLoadStateNamed (core, coreController->saveState, SAVESTATE_SAVEDATA & SAVESTATE_RTC)) { fprintf(stderr, "Unable to load save state\n"); } } diff --git a/src/multiplayer_controller.c b/src/multiplayer_controller.c index 232aa41..5fd25a3 100644 --- a/src/multiplayer_controller.c +++ b/src/multiplayer_controller.c @@ -1,3 +1,5 @@ +#include + #include #include #include diff --git a/src/packet.c b/src/packet.c index 7a24bf6..ee156af 100644 --- a/src/packet.c +++ b/src/packet.c @@ -4,23 +4,28 @@ #include #include #include +#include #define PRINT_DEBUG(NAME, CLIENT_FD) \ printf ("Received packet %s from client fd %d\n", #NAME, CLIENT_FD); bool -msPacketHandle(struct msPacket *packet, int client_fd, +msPacketHandle(struct msPacket *packet, int clientFd, struct msClientConnectionData *const data) { bool result = false; printf("Received packet %lu\n", packet->id); switch (packet->id) { case PACKET_GET_HELLO: - PRINT_DEBUG(PACKET_HELLO, client_fd); - result = msPacketHelloGet(packet, client_fd, data); + PRINT_DEBUG(PACKET_HELLO, clientFd); + result = msPacketHelloGet(packet, clientFd, data); break; case PACKET_GET_KEY_DOWN: - PRINT_DEBUG(PACKET_KEY_DOWN, client_fd); - result = msPacketKeyDownGet(packet, client_fd, data); + PRINT_DEBUG(PACKET_KEY_DOWN, clientFd); + result = msPacketKeyDownGet(packet, clientFd, data); + break; + case PACKET_GET_SAVE_REQUEST: + PRINT_DEBUG(PACKET_SAVE_REQUEST, clientFd); + result = msPacketSaveRequestGet(packet, clientFd, data); break; } return result; @@ -61,7 +66,7 @@ msPacketSend(const struct msPacket *const packet, struct msClientConnectionData if (!msPacketWrite(fd, (const void *)&size, sizeof packet->size)) { goto return_ms_packet_send; } - if (!msPacketWrite(fd, (const void *)packet->raw_data, sizeof *packet->raw_data * packet->size)){ + if (!msPacketWrite(fd, (const void *)packet->rawData, sizeof *packet->rawData * packet->size)){ goto return_ms_packet_send; } result = true; @@ -71,52 +76,52 @@ return_ms_packet_send: } struct msPacket * -msPacketNew(const size_t id, const size_t size, unsigned char *raw_data) { +msPacketNew(const size_t id, const size_t size, unsigned char *rawData) { struct msPacket *packet = malloc(sizeof *packet); packet->id = id; packet->size = size; - packet->raw_data = raw_data; + packet->rawData = rawData; return packet; } void msPacketDestroy(struct msPacket **packet) { - if ((*packet)->raw_data) { - free((*packet)->raw_data); + if ((*packet)->rawData) { + free((*packet)->rawData); } free(*packet); *packet=NULL; } struct msPacket * -msPacketRead(int client_fd) { +msPacketRead(int clientFd) { struct msPacket *packet = NULL; size_t id = 0; size_t size = 0; ssize_t result; - unsigned char *raw_data = NULL; + unsigned char *rawData = NULL; - result = read(client_fd, &id, sizeof id); + result = read(clientFd, &id, sizeof id); if (result < sizeof id) { printf("Unable to read id\n"); goto return_read_packet; } id = be64toh(id); - result = read(client_fd, &size, sizeof size); + result = read(clientFd, &size, sizeof size); if (result < sizeof size) { printf("Unable to read packet\n"); goto return_read_packet; } size = be64toh(size); - raw_data = malloc(size); + rawData = malloc(size); size_t to_read_size = size; while (to_read_size > 0) { - result = read(client_fd, &raw_data[size - to_read_size], to_read_size); + result = read(clientFd, &rawData[size - to_read_size], to_read_size); if (result == -1) { - printf("Unable to read raw_data\n"); + printf("Unable to read rawData\n"); goto return_read_packet; } to_read_size -= result; @@ -126,10 +131,10 @@ msPacketRead(int client_fd) { packet = calloc (1, sizeof *packet); packet->id = id; packet->size = size; - packet->raw_data = raw_data; + packet->rawData = rawData; return_read_packet: - if (!packet && raw_data) { - free(raw_data); + if (!packet && rawData) { + free(rawData); } return packet; } diff --git a/src/packet/hello.c b/src/packet/hello.c index bd69bd5..762a83b 100644 --- a/src/packet/hello.c +++ b/src/packet/hello.c @@ -1,8 +1,11 @@ #include #include +#include +#include #include +#include #include #include @@ -30,13 +33,8 @@ msThreadCallbackStart(struct mCoreThread *threadContext) { sigemptyset(&set); sigaddset(&set, SIGPIPE); pthread_sigmask(SIG_BLOCK, &set, NULL); - struct msClientConnectionData *data = (struct msClientConnectionData *)threadContext->userData; - struct msCoreController *coreController = data->coreController; - struct mCore *core = coreController->threadContext.core; - if (!mCoreLoadStateNamed (core, coreController->saveState, 0)) { // SAVESTATE_SAVEDATA & SAVESTATE_RTC)) { - fprintf(stderr, "Unable to load save state\n"); - } } + void msThreadCallbackSetFrame(struct mCoreThread *threadContext) { #define SEC_TO_NANO(sec) \ @@ -45,8 +43,8 @@ msThreadCallbackSetFrame(struct mCoreThread *threadContext) { unsigned int stride; color_t *outputBuffer; unsigned width, height; - unsigned char *raw_data = NULL; - size_t raw_data_len = 0; + unsigned char *rawData = NULL; + size_t rawDataLen = 0; struct msPacketSendFrame *send_frame = NULL; struct msPacket *packet = NULL; struct timespec current_date; @@ -70,12 +68,12 @@ msThreadCallbackSetFrame(struct mCoreThread *threadContext) { data->coreController->threadContext.core->desiredVideoDimensions(data->coreController->threadContext.core, &width, &height); send_frame = msPacketSendFrameNew(stride, width * height, outputBuffer); - raw_data = msPacketSendFrameSerialize(send_frame, &raw_data_len); - if (!raw_data) { + rawData = msPacketSendFrameSerialize(send_frame, &rawDataLen); + if (!rawData) { goto return_ms_thread_callback_set_frame; } - packet = msPacketNew(PACKET_SEND_FRAME, raw_data_len, raw_data); + packet = msPacketNew(PACKET_SEND_FRAME, rawDataLen, rawData); msPacketSend(packet, data); return_ms_thread_callback_set_frame: @@ -113,7 +111,7 @@ msPacketHelloGet(const struct msPacket *packet, int client_fd, struct msPacketHello *hello = NULL; unsigned char *rom = NULL; unsigned char *savestate = NULL; - FILE *fp = fmemopen(packet->raw_data, packet->size, "r"); + FILE *fp = fmemopen(packet->rawData, packet->size, "r"); if (!fp) { printf("Unable to fmemopen\n"); goto return_get_packet_hello; diff --git a/src/packet/key_down.c b/src/packet/key_down.c index c8b9c70..d853bc6 100644 --- a/src/packet/key_down.c +++ b/src/packet/key_down.c @@ -2,6 +2,7 @@ #include #include +#include #include #include @@ -13,7 +14,7 @@ msPacketKeyDownGet(const struct msPacket *packet, int clientFd, struct msClientC struct msPacketKeyDown *keyDown = NULL; int key = 0; char isPressed = 0; - FILE *fp = fmemopen(packet->raw_data, packet->size, "r"); + FILE *fp = fmemopen(packet->rawData, packet->size, "r"); if (1 != fread(&isPressed, sizeof isPressed, 1, fp)) { goto return_ms_packet_key_down_get; } diff --git a/src/packet/save_request.c b/src/packet/save_request.c new file mode 100644 index 0000000..8ccd570 --- /dev/null +++ b/src/packet/save_request.c @@ -0,0 +1,178 @@ +#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; + unsigned char *resultTmp= realloc(result, sizeof *result * *len); + if (!resultTmp) { + free(result); + result = NULL; + goto return_vfile_to_bytes; + } + result = resultTmp; + // memcpy_s not available in linux. + memcpy(&result[*len-1-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."); + 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_SAVEDATA & SAVESTATE_RTC); + 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); +return_ms_packet_save_request_handle: + msPacketSaveRequestDestroy(&self); + return result; +} diff --git a/src/packet/save_response.c b/src/packet/save_response.c new file mode 100644 index 0000000..37f3b41 --- /dev/null +++ b/src/packet/save_response.c @@ -0,0 +1,49 @@ +#include +#include + +#include + +void +msPacketSaveResponseDestroy(struct msPacketSaveResponse **selfPtr) { + free(*selfPtr); + *selfPtr = NULL; +} + +struct msPacketSaveResponse * +msPacketSaveResponseNew(uint64_t identifier, size_t saveLen, unsigned char *save) { + struct msPacketSaveResponse *self = NULL; + self = malloc(sizeof *self); + self->identifier = identifier; + self->saveLen = saveLen; + self->save = save; + return self; +} + +unsigned char * +msPacketSaveResponseSerialize(struct msPacketSaveResponse *const self, size_t *len) { + unsigned char *result = NULL; + size_t identifier = self->identifier; + size_t saveLen = self->saveLen; + size_t currentCursor = 0; + + if (!len) { + goto return_ms_packet_save_response_serialize; + } + + *len = sizeof identifier + sizeof saveLen + sizeof *result * saveLen; + result = malloc(*len); + + htobe64(identifier); + htobe64(saveLen); + + memcpy(&result[currentCursor], &identifier, sizeof identifier); // NOLINT + currentCursor += sizeof identifier; + + memcpy(&result[currentCursor], &saveLen, sizeof saveLen); // NOLINT + currentCursor += sizeof saveLen; + + memcpy(&result[currentCursor], self->save, sizeof *result * saveLen); // NOLINT + +return_ms_packet_save_response_serialize: + return result; +} diff --git a/src/packet/send_frame.c b/src/packet/send_frame.c index 831ec76..2ade8cc 100644 --- a/src/packet/send_frame.c +++ b/src/packet/send_frame.c @@ -1,3 +1,4 @@ +#include #include #include