Adding the send frame handling.
This commit is contained in:
parent
0aaf6079b0
commit
91e7ff6d66
@ -14,6 +14,7 @@ struct msClientConnectionData {
|
|||||||
size_t numberOfThread;
|
size_t numberOfThread;
|
||||||
int clientFd;
|
int clientFd;
|
||||||
struct msCoreController *coreController;
|
struct msCoreController *coreController;
|
||||||
|
pthread_mutex_t *mutexSendPacket;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -30,4 +30,6 @@ void
|
|||||||
msCoreControllerThreadStart (struct msCoreController *const core_controller);
|
msCoreControllerThreadStart (struct msCoreController *const core_controller);
|
||||||
void
|
void
|
||||||
msCoreControllerSetFrameCallback(struct msCoreController *const self, void(*callback)(struct mCoreThread *));
|
msCoreControllerSetFrameCallback(struct msCoreController *const self, void(*callback)(struct mCoreThread *));
|
||||||
|
void
|
||||||
|
msCoreControllerSetStartCallback(struct msCoreController *const self, void(*callback)(struct mCoreThread *));
|
||||||
#endif
|
#endif
|
||||||
|
@ -23,7 +23,7 @@ struct msPacket {
|
|||||||
//! The size of the data contained in the packet.
|
//! The size of the data contained in the packet.
|
||||||
size_t size;
|
size_t size;
|
||||||
//! The data as a byte array. (Not null terminated.)
|
//! The data as a byte array. (Not null terminated.)
|
||||||
char *raw_data;
|
unsigned char *raw_data;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -32,6 +32,18 @@ struct msPacket {
|
|||||||
bool
|
bool
|
||||||
msPacketHandle(struct msPacket *packet, int client_fd, struct msClientConnectionData *const data);
|
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.
|
* When done with a packet it must be destroyed using this method.
|
||||||
*/
|
*/
|
||||||
|
43
include/msgba/packet/send_frame.h
Normal file
43
include/msgba/packet/send_frame.h
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
#ifndef MS_PACKET_SEND_HELLO
|
||||||
|
#define MS_PACKET_SEND_HELLO
|
||||||
|
#include <msgba/core_controller.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
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
|
@ -9,6 +9,7 @@ sources = [
|
|||||||
'src/multiplayer_controller.c',
|
'src/multiplayer_controller.c',
|
||||||
'src/packet.c',
|
'src/packet.c',
|
||||||
'src/packet/hello.c',
|
'src/packet/hello.c',
|
||||||
|
'src/packet/send_frame.c',
|
||||||
'src/client_connection_data.c',
|
'src/client_connection_data.c',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
#include <msgba/core_controller.h>
|
#include <msgba/core_controller.h>
|
||||||
#include <msgba/client_connection_data.h>
|
#include <msgba/client_connection_data.h>
|
||||||
struct msClientConnectionData *
|
struct msClientConnectionData *
|
||||||
@ -6,6 +8,8 @@ msClientConnectionDataNew(size_t numberOfThread, int clientFd) {
|
|||||||
data->numberOfThread = numberOfThread;
|
data->numberOfThread = numberOfThread;
|
||||||
data->clientFd = clientFd;
|
data->clientFd = clientFd;
|
||||||
data->coreController = NULL;
|
data->coreController = NULL;
|
||||||
|
data->mutexSendPacket = malloc(sizeof *data->mutexSendPacket);
|
||||||
|
pthread_mutex_init(data->mutexSendPacket, NULL);
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -14,6 +18,8 @@ msClientConnectionDataDestroy(struct msClientConnectionData **data) {
|
|||||||
if ((*data)->coreController) {
|
if ((*data)->coreController) {
|
||||||
msCoreControllerDestroy(&(*data)->coreController);
|
msCoreControllerDestroy(&(*data)->coreController);
|
||||||
}
|
}
|
||||||
|
free((*data)->mutexSendPacket);
|
||||||
|
(*data)->mutexSendPacket = NULL;
|
||||||
free(*data);
|
free(*data);
|
||||||
*data = NULL;
|
*data = NULL;
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,7 @@ msCoreControllerLoadGame (const unsigned char *rom, size_t rom_len,
|
|||||||
unsigned int width;
|
unsigned int width;
|
||||||
unsigned int height;
|
unsigned int height;
|
||||||
mCoreInitConfig(core, NULL);
|
mCoreInitConfig(core, NULL);
|
||||||
mCoreConfigSetIntValue(&core->config, "logLevel", mLOG_FATAL & mLOG_ERROR & mLOG_WARN);
|
mCoreConfigSetIntValue(&core->config, "logLevel", mLOG_FATAL);
|
||||||
|
|
||||||
core->desiredVideoDimensions(core, &width, &height);
|
core->desiredVideoDimensions(core, &width, &height);
|
||||||
color_t *outputBuffer = malloc((sizeof *outputBuffer) * width * height);
|
color_t *outputBuffer = malloc((sizeof *outputBuffer) * width * height);
|
||||||
@ -58,6 +58,10 @@ void
|
|||||||
msCoreControllerSetFrameCallback(struct msCoreController *const self, void(*callback)(struct mCoreThread *)) {
|
msCoreControllerSetFrameCallback(struct msCoreController *const self, void(*callback)(struct mCoreThread *)) {
|
||||||
self->threadContext.frameCallback = callback;
|
self->threadContext.frameCallback = callback;
|
||||||
}
|
}
|
||||||
|
void
|
||||||
|
msCoreControllerSetStartCallback(struct msCoreController *const self, void(*callback)(struct mCoreThread *)) {
|
||||||
|
self->threadContext.startCallback = callback;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
msCoreControllerThreadStart (struct msCoreController *const core_controller) {
|
msCoreControllerThreadStart (struct msCoreController *const core_controller) {
|
||||||
|
50
src/packet.c
50
src/packet.c
@ -1,3 +1,4 @@
|
|||||||
|
#include <pthread.h>
|
||||||
#include <endian.h>
|
#include <endian.h>
|
||||||
|
|
||||||
#include <msgba/packet.h>
|
#include <msgba/packet.h>
|
||||||
@ -5,6 +6,7 @@
|
|||||||
|
|
||||||
#define PRINT_DEBUG(NAME, CLIENT_FD) \
|
#define PRINT_DEBUG(NAME, CLIENT_FD) \
|
||||||
printf ("Received packet %s from client fd %d\n", #NAME, CLIENT_FD);
|
printf ("Received packet %s from client fd %d\n", #NAME, CLIENT_FD);
|
||||||
|
|
||||||
bool
|
bool
|
||||||
msPacketHandle(struct msPacket *packet, int client_fd,
|
msPacketHandle(struct msPacket *packet, int client_fd,
|
||||||
struct msClientConnectionData *const data) {
|
struct msClientConnectionData *const data) {
|
||||||
@ -18,15 +20,49 @@ msPacketHandle(struct msPacket *packet, int client_fd,
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
static bool
|
||||||
msPacketSend(const struct msPacket *const packet, int fd) {
|
msPacketWrite(int fd, const void *data, size_t len) {
|
||||||
write(fd, (const void *)packet->id, sizeof packet->id);
|
bool result = false;
|
||||||
write(fd, (const void *)packet->size, sizeof packet->size);
|
ssize_t written_bytes = 0;
|
||||||
write(fd, (const void *)packet->raw_data, sizeof *packet->raw_data * packet->size);
|
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 *
|
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);
|
struct msPacket *packet = malloc(sizeof *packet);
|
||||||
packet->id = id;
|
packet->id = id;
|
||||||
packet->size = size;
|
packet->size = size;
|
||||||
@ -50,7 +86,7 @@ msPacketRead(int client_fd) {
|
|||||||
size_t id = 0;
|
size_t id = 0;
|
||||||
size_t size = 0;
|
size_t size = 0;
|
||||||
ssize_t result;
|
ssize_t result;
|
||||||
char *raw_data = NULL;
|
unsigned char *raw_data = NULL;
|
||||||
|
|
||||||
result = read(client_fd, &id, sizeof id);
|
result = read(client_fd, &id, sizeof id);
|
||||||
if (result < sizeof id) {
|
if (result < sizeof id) {
|
||||||
|
@ -1,6 +1,10 @@
|
|||||||
|
#include <sys/signal.h>
|
||||||
|
|
||||||
|
#include <msgba/packet/send_frame.h>
|
||||||
#include <msgba/packet.h>
|
#include <msgba/packet.h>
|
||||||
#include <msgba/packet/hello.h>
|
#include <msgba/packet/hello.h>
|
||||||
#include <msgba/core_controller.h>
|
#include <msgba/core_controller.h>
|
||||||
|
|
||||||
void
|
void
|
||||||
msPacketHelloDestroy(struct msPacketHello **hello) {
|
msPacketHelloDestroy(struct msPacketHello **hello) {
|
||||||
if ((*hello)->rom) {
|
if ((*hello)->rom) {
|
||||||
@ -15,15 +19,36 @@ msPacketHelloDestroy(struct msPacketHello **hello) {
|
|||||||
*hello = NULL;
|
*hello = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
msThreadCallbackStart(struct mCoreThread *threadContext) {
|
||||||
|
sigset_t set;
|
||||||
|
sigemptyset(&set);
|
||||||
|
sigaddset(&set, SIGPIPE);
|
||||||
|
pthread_sigmask(SIG_BLOCK, &set, NULL);
|
||||||
|
}
|
||||||
void
|
void
|
||||||
msThreadCallbackSetFrame(struct mCoreThread *threadContext) {
|
msThreadCallbackSetFrame(struct mCoreThread *threadContext) {
|
||||||
struct msClientConnectionData *data = (struct msClientConnectionData *)threadContext->userData;
|
struct msClientConnectionData *data = (struct msClientConnectionData *)threadContext->userData;
|
||||||
unsigned int stride = data->coreController->stride;
|
unsigned int stride = data->coreController->stride;
|
||||||
int client_fd = data->clientFd;
|
|
||||||
color_t *outputBuffer = data->coreController->outputBuffer;
|
color_t *outputBuffer = data->coreController->outputBuffer;
|
||||||
unsigned width, height;
|
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);
|
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
|
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);
|
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);
|
data->coreController = msCoreControllerLoadGame(hello->rom, hello->size_rom, hello->savestate, hello->size_savestate, data);
|
||||||
msCoreControllerSetFrameCallback(data->coreController, &msThreadCallbackSetFrame);
|
msCoreControllerSetFrameCallback(data->coreController, &msThreadCallbackSetFrame);
|
||||||
|
msCoreControllerSetStartCallback(data->coreController, &msThreadCallbackStart);
|
||||||
msCoreControllerThreadStart(data->coreController);
|
msCoreControllerThreadStart(data->coreController);
|
||||||
result = true;
|
result = true;
|
||||||
return_ms_packet_hello_handle:
|
return_ms_packet_hello_handle:
|
||||||
|
52
src/packet/send_frame.c
Normal file
52
src/packet/send_frame.c
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
#include <endian.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include <msgba/packet/send_frame.h>
|
||||||
|
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;
|
||||||
|
}
|
16
tester.pl
16
tester.pl
@ -29,7 +29,21 @@ open my $fh_packet, '>', \$packet;
|
|||||||
write_packet($fh_packet, $PACKET_HELLO, \$packet_hello);
|
write_packet($fh_packet, $PACKET_HELLO, \$packet_hello);
|
||||||
close $fh_packet;
|
close $fh_packet;
|
||||||
print $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 {
|
sub write_packet {
|
||||||
my $fh = shift;
|
my $fh = shift;
|
||||||
|
Loading…
Reference in New Issue
Block a user