Adding the send frame handling.
This commit is contained in:
parent
0aaf6079b0
commit
91e7ff6d66
@ -14,6 +14,7 @@ struct msClientConnectionData {
|
||||
size_t numberOfThread;
|
||||
int clientFd;
|
||||
struct msCoreController *coreController;
|
||||
pthread_mutex_t *mutexSendPacket;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
*/
|
||||
|
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/packet.c',
|
||||
'src/packet/hello.c',
|
||||
'src/packet/send_frame.c',
|
||||
'src/client_connection_data.c',
|
||||
]
|
||||
|
||||
|
@ -1,3 +1,5 @@
|
||||
#include <pthread.h>
|
||||
|
||||
#include <msgba/core_controller.h>
|
||||
#include <msgba/client_connection_data.h>
|
||||
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;
|
||||
}
|
||||
|
@ -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) {
|
||||
|
50
src/packet.c
50
src/packet.c
@ -1,3 +1,4 @@
|
||||
#include <pthread.h>
|
||||
#include <endian.h>
|
||||
|
||||
#include <msgba/packet.h>
|
||||
@ -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) {
|
||||
|
@ -1,6 +1,10 @@
|
||||
#include <sys/signal.h>
|
||||
|
||||
#include <msgba/packet/send_frame.h>
|
||||
#include <msgba/packet.h>
|
||||
#include <msgba/packet/hello.h>
|
||||
#include <msgba/core_controller.h>
|
||||
|
||||
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:
|
||||
|
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);
|
||||
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;
|
||||
|
Loading…
Reference in New Issue
Block a user