From 91e7ff6d6661dc5bd60d7ef0c57c213b01f7fb79 Mon Sep 17 00:00:00 2001 From: Sergiotarxz Date: Mon, 13 Mar 2023 00:06:19 +0100 Subject: [PATCH] Adding the send frame handling. --- include/msgba/client_connection_data.h | 1 + include/msgba/core_controller.h | 2 + include/msgba/packet.h | 14 ++++++- include/msgba/packet/send_frame.h | 43 +++++++++++++++++++++ meson.build | 1 + src/client_connection_data.c | 6 +++ src/core_controller.c | 6 ++- src/packet.c | 50 +++++++++++++++++++++---- src/packet/hello.c | 30 ++++++++++++++- src/packet/send_frame.c | 52 ++++++++++++++++++++++++++ tester.pl | 16 +++++++- 11 files changed, 209 insertions(+), 12 deletions(-) create mode 100644 include/msgba/packet/send_frame.h create mode 100644 src/packet/send_frame.c diff --git a/include/msgba/client_connection_data.h b/include/msgba/client_connection_data.h index 4037652..f4d0ff2 100644 --- a/include/msgba/client_connection_data.h +++ b/include/msgba/client_connection_data.h @@ -14,6 +14,7 @@ struct msClientConnectionData { size_t numberOfThread; int clientFd; struct msCoreController *coreController; + pthread_mutex_t *mutexSendPacket; }; /** diff --git a/include/msgba/core_controller.h b/include/msgba/core_controller.h index 3791a2f..46f77ab 100644 --- a/include/msgba/core_controller.h +++ b/include/msgba/core_controller.h @@ -30,4 +30,6 @@ void msCoreControllerThreadStart (struct msCoreController *const core_controller); void msCoreControllerSetFrameCallback(struct msCoreController *const self, void(*callback)(struct mCoreThread *)); +void +msCoreControllerSetStartCallback(struct msCoreController *const self, void(*callback)(struct mCoreThread *)); #endif diff --git a/include/msgba/packet.h b/include/msgba/packet.h index cfce10a..d0301cf 100644 --- a/include/msgba/packet.h +++ b/include/msgba/packet.h @@ -23,7 +23,7 @@ struct msPacket { //! The size of the data contained in the packet. size_t size; //! The data as a byte array. (Not null terminated.) - char *raw_data; + unsigned char *raw_data; }; /** @@ -32,6 +32,18 @@ struct msPacket { bool msPacketHandle(struct msPacket *packet, int client_fd, struct msClientConnectionData *const data); +/** + * Creates a new packet object. + */ +struct msPacket * +msPacketNew(const size_t id, const size_t size, unsigned char *raw_data); + +/** + * Sends the packet to the client. + */ +bool +msPacketSend(const struct msPacket *const packet, struct msClientConnectionData *const data); + /** * When done with a packet it must be destroyed using this method. */ diff --git a/include/msgba/packet/send_frame.h b/include/msgba/packet/send_frame.h new file mode 100644 index 0000000..0bc83b7 --- /dev/null +++ b/include/msgba/packet/send_frame.h @@ -0,0 +1,43 @@ +#ifndef MS_PACKET_SEND_HELLO +#define MS_PACKET_SEND_HELLO +#include +#include +struct msPacket; + +/** + * Structure representing a video frame packet. + * The combination of these packets allow the video to be seen in the client. + */ +struct msPacketSendFrame { + //! The width + unsigned int stride; + //! The full size of the buffer. + size_t outputBufferSize; + //! The rgbx buffer. + color_t *outputBuffer; +}; + +/** + * Ends the life in memory of the send_frame packet. + * @param send_frame A reference to a pointer to a send_frame packet. + */ +void +msPacketSendFrameDestroy(struct msPacketSendFrame **send_frame); + +/** + * Creates a new send_frame packet. + * @param stride The witdh + * @param outputBufferSize The size of the outputBuffer + * @param outputBuffer The rgbx array. + */ +struct msPacketSendFrame * +msPacketSendFrameNew(unsigned int stride, size_t outputBufferSize, color_t *const outputBuffer); + +/** + * Converts the struct to a byte array with size len. + * @param send_frame The object + * @param len The returned byte array size. + */ +unsigned char * +msPacketSendFrameSerialize(struct msPacketSendFrame *const send_frame, size_t *len); +#endif diff --git a/meson.build b/meson.build index 6ea4309..8c3a133 100644 --- a/meson.build +++ b/meson.build @@ -9,6 +9,7 @@ sources = [ 'src/multiplayer_controller.c', 'src/packet.c', 'src/packet/hello.c', + 'src/packet/send_frame.c', 'src/client_connection_data.c', ] diff --git a/src/client_connection_data.c b/src/client_connection_data.c index 6d4b50b..2e7f807 100644 --- a/src/client_connection_data.c +++ b/src/client_connection_data.c @@ -1,3 +1,5 @@ +#include + #include #include struct msClientConnectionData * @@ -6,6 +8,8 @@ msClientConnectionDataNew(size_t numberOfThread, int clientFd) { data->numberOfThread = numberOfThread; data->clientFd = clientFd; data->coreController = NULL; + data->mutexSendPacket = malloc(sizeof *data->mutexSendPacket); + pthread_mutex_init(data->mutexSendPacket, NULL); return data; } @@ -14,6 +18,8 @@ msClientConnectionDataDestroy(struct msClientConnectionData **data) { if ((*data)->coreController) { msCoreControllerDestroy(&(*data)->coreController); } + free((*data)->mutexSendPacket); + (*data)->mutexSendPacket = NULL; free(*data); *data = NULL; } diff --git a/src/core_controller.c b/src/core_controller.c index 96bd315..0f1ce0a 100644 --- a/src/core_controller.c +++ b/src/core_controller.c @@ -38,7 +38,7 @@ msCoreControllerLoadGame (const unsigned char *rom, size_t rom_len, unsigned int width; unsigned int height; mCoreInitConfig(core, NULL); - mCoreConfigSetIntValue(&core->config, "logLevel", mLOG_FATAL & mLOG_ERROR & mLOG_WARN); + mCoreConfigSetIntValue(&core->config, "logLevel", mLOG_FATAL); core->desiredVideoDimensions(core, &width, &height); color_t *outputBuffer = malloc((sizeof *outputBuffer) * width * height); @@ -58,6 +58,10 @@ void msCoreControllerSetFrameCallback(struct msCoreController *const self, void(*callback)(struct mCoreThread *)) { self->threadContext.frameCallback = callback; } +void +msCoreControllerSetStartCallback(struct msCoreController *const self, void(*callback)(struct mCoreThread *)) { + self->threadContext.startCallback = callback; +} void msCoreControllerThreadStart (struct msCoreController *const core_controller) { diff --git a/src/packet.c b/src/packet.c index 44a394c..56b4ed0 100644 --- a/src/packet.c +++ b/src/packet.c @@ -1,3 +1,4 @@ +#include #include #include @@ -5,6 +6,7 @@ #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, struct msClientConnectionData *const data) { @@ -18,15 +20,49 @@ msPacketHandle(struct msPacket *packet, int client_fd, return result; } -void -msPacketSend(const struct msPacket *const packet, int fd) { - write(fd, (const void *)packet->id, sizeof packet->id); - write(fd, (const void *)packet->size, sizeof packet->size); - write(fd, (const void *)packet->raw_data, sizeof *packet->raw_data * packet->size); +static bool +msPacketWrite(int fd, const void *data, size_t len) { + bool result = false; + ssize_t written_bytes = 0; + const unsigned char *bytes = (const unsigned char *)data; + while (written_bytes < len) { + ssize_t wrote_in_this_write = write(fd, (const void *)&bytes[written_bytes], (sizeof *bytes * len) - written_bytes); + if (wrote_in_this_write == -1) { + goto return_ms_packet_write; + } + written_bytes += wrote_in_this_write; + } + result = true; +return_ms_packet_write: + return result; +} + +bool +msPacketSend(const struct msPacket *const packet, struct msClientConnectionData *const data) { + pthread_mutex_lock(data->mutexSendPacket); + int fd = data->clientFd; + size_t id = packet->id; + size_t size = packet->size; + bool result = false; + id = htobe64(id); + size = htobe64(size); + if(!msPacketWrite(fd, (const void *)&id, sizeof packet->id)) { + goto return_ms_packet_send; + } + 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)){ + goto return_ms_packet_send; + } + result = true; +return_ms_packet_send: + pthread_mutex_unlock(data->mutexSendPacket); + return result; } struct msPacket * -msPacketNew(const size_t id, const size_t size, char *raw_data) { +msPacketNew(const size_t id, const size_t size, unsigned char *raw_data) { struct msPacket *packet = malloc(sizeof *packet); packet->id = id; packet->size = size; @@ -50,7 +86,7 @@ msPacketRead(int client_fd) { size_t id = 0; size_t size = 0; ssize_t result; - char *raw_data = NULL; + unsigned char *raw_data = NULL; result = read(client_fd, &id, sizeof id); if (result < sizeof id) { diff --git a/src/packet/hello.c b/src/packet/hello.c index 2d2f66d..5d6cadc 100644 --- a/src/packet/hello.c +++ b/src/packet/hello.c @@ -1,6 +1,10 @@ +#include + +#include #include #include #include + void msPacketHelloDestroy(struct msPacketHello **hello) { if ((*hello)->rom) { @@ -15,15 +19,36 @@ msPacketHelloDestroy(struct msPacketHello **hello) { *hello = NULL; } +void +msThreadCallbackStart(struct mCoreThread *threadContext) { + sigset_t set; + sigemptyset(&set); + sigaddset(&set, SIGPIPE); + pthread_sigmask(SIG_BLOCK, &set, NULL); +} void msThreadCallbackSetFrame(struct mCoreThread *threadContext) { struct msClientConnectionData *data = (struct msClientConnectionData *)threadContext->userData; unsigned int stride = data->coreController->stride; - int client_fd = data->clientFd; color_t *outputBuffer = data->coreController->outputBuffer; unsigned width, height; + unsigned char *raw_data; + size_t raw_data_len = 0; + struct msPacketSendFrame *send_frame; + struct msPacket *packet; + + + 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); + + packet = msPacketNew(PACKET_SEND_FRAME, raw_data_len, raw_data); + msPacketSend(packet, data); + + msPacketSendFrameDestroy(&send_frame); + msPacketDestroy(&packet); } bool @@ -37,6 +62,7 @@ msPacketHelloHandle(const struct msPacket *packet, struct msPacketHello *hello, printf("Loading game and save for client_fd %d\n", data->clientFd); data->coreController = msCoreControllerLoadGame(hello->rom, hello->size_rom, hello->savestate, hello->size_savestate, data); msCoreControllerSetFrameCallback(data->coreController, &msThreadCallbackSetFrame); + msCoreControllerSetStartCallback(data->coreController, &msThreadCallbackStart); msCoreControllerThreadStart(data->coreController); result = true; return_ms_packet_hello_handle: diff --git a/src/packet/send_frame.c b/src/packet/send_frame.c new file mode 100644 index 0000000..a8c2c8d --- /dev/null +++ b/src/packet/send_frame.c @@ -0,0 +1,52 @@ +#include +#include + +#include +void +msPacketSendFrameDestroy(struct msPacketSendFrame **send_frame) { + free ((*send_frame)->outputBuffer); + (*send_frame)->outputBuffer = NULL; + free (*send_frame); + *send_frame = NULL; +} + +struct msPacketSendFrame * +msPacketSendFrameNew(unsigned int stride, size_t outputBufferSize, color_t *const outputBuffer) { + struct msPacketSendFrame *self = malloc(sizeof *self); + color_t *outputBufferClone = malloc (sizeof *outputBufferClone * outputBufferSize); + for (size_t i = 0; i < outputBufferSize; i++) { + outputBufferClone[i] = outputBuffer[i]; + } + self->outputBufferSize = outputBufferSize; + self->stride = stride; + self->outputBuffer = outputBufferClone; + return self; +} + +unsigned char * +msPacketSendFrameSerialize(struct msPacketSendFrame *const self, size_t *len) { + unsigned char *bytes; + unsigned int stride = self->stride; + size_t outputBufferSizeBytes = self->outputBufferSize * sizeof *self->outputBuffer; + stride = htobe32(stride); + *len = (sizeof self->stride) + (sizeof self->outputBufferSize) + (outputBufferSizeBytes); + outputBufferSizeBytes = htobe64(outputBufferSizeBytes); + bytes = malloc(*len); +#define GOTO_END_SERIALIZE_FAIL() \ + free(bytes); \ + bytes = NULL; + goto return_ms_packet_send_frame_serialize; + FILE *fp = fmemopen(bytes, sizeof *bytes * *len, "w"); + if (fwrite(&self->stride, sizeof self->stride, 1, fp) == -1) { + GOTO_END_SERIALIZE_FAIL(); + } + if (fwrite(&outputBufferSizeBytes, sizeof outputBufferSizeBytes, 1, fp) == -1) { + GOTO_END_SERIALIZE_FAIL(); + } + if (fwrite(self->outputBuffer, sizeof *self->outputBuffer, self->outputBufferSize, fp) == -1) { + GOTO_END_SERIALIZE_FAIL(); + } + fclose(fp); +return_ms_packet_send_frame_serialize: + return bytes; +} diff --git a/tester.pl b/tester.pl index 7ac9483..0d4a97d 100644 --- a/tester.pl +++ b/tester.pl @@ -29,7 +29,21 @@ open my $fh_packet, '>', \$packet; write_packet($fh_packet, $PACKET_HELLO, \$packet_hello); close $fh_packet; print $fh $packet; -sleep 1 while 1; + +while (retrieve_packet($fh)) { +} + +sub retrieve_packet { + my $fh = shift; + (read $fh, my $id, 8) or return 0; + $id = unpack('Q>', $id); + (read $fh, my $size, 8) or return 0; + $size = unpack('Q>', $size); + (read $fh, my $raw_data, $size) or return 0; + say $id; + say $size; + return 1; +} sub write_packet { my $fh = shift;