Adding save fetch and response to that fetch and improving documentation.
This commit is contained in:
parent
663a7622ff
commit
c8ea2f847b
@ -7,6 +7,7 @@
|
|||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
|
|
||||||
struct msCoreController;
|
struct msCoreController;
|
||||||
|
struct msPacketSaveRequestData;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Struct representing everything needed while a connection is established.
|
* Struct representing everything needed while a connection is established.
|
||||||
@ -24,6 +25,12 @@ struct msClientConnectionData {
|
|||||||
pthread_mutex_t *mutexPressKey;
|
pthread_mutex_t *mutexPressKey;
|
||||||
//! The last time we sent a frame.
|
//! The last time we sent a frame.
|
||||||
struct timespec *lastFrameDate;
|
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;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
#ifndef MS_CORE_CONTROLLER
|
#ifndef MS_CORE_CONTROLLER
|
||||||
#define MS_CORE_CONTROLLER
|
#define MS_CORE_CONTROLLER
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
#include <mgba/core/core.h>
|
|
||||||
#include <mgba/core/thread.h>
|
#include <mgba/core/thread.h>
|
||||||
|
typedef uint32_t color_t;
|
||||||
|
|
||||||
#include <msgba/client_connection_data.h>
|
#include <msgba/client_connection_data.h>
|
||||||
|
|
||||||
|
@ -9,10 +9,18 @@
|
|||||||
* The possible values for a packet id.
|
* The possible values for a packet id.
|
||||||
*/
|
*/
|
||||||
enum {
|
enum {
|
||||||
PACKET_GET_HELLO, //! Packet id for get hello.
|
//! Packet id for get hello.
|
||||||
PACKET_SEND_FRAME, //! Packet id for send frame.
|
PACKET_GET_HELLO,
|
||||||
PACKET_GET_KEY_DOWN, //! Packet id for pressing a key.
|
//! Packet id for send frame.
|
||||||
PACKETS_NUMBER //! The number of recognized packets.
|
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.
|
//! 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.)
|
||||||
unsigned char *raw_data;
|
unsigned char *rawData;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Asks the code to handle a concrete packet comming from a client.
|
* Asks the code to handle a concrete packet comming from a client.
|
||||||
*/
|
*/
|
||||||
bool
|
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.
|
* Creates a new packet object.
|
||||||
*/
|
*/
|
||||||
struct msPacket *
|
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.
|
* Sends the packet to the client.
|
||||||
@ -56,4 +64,4 @@ msPacketDestroy(struct msPacket **packet);
|
|||||||
* Blocks the current thread.
|
* Blocks the current thread.
|
||||||
*/
|
*/
|
||||||
struct msPacket *
|
struct msPacket *
|
||||||
msPacketRead(int client_fd);
|
msPacketRead(int clientFd);
|
||||||
|
56
include/msgba/packet/save_request.h
Normal file
56
include/msgba/packet/save_request.h
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
#ifndef MS_PACKET_SAVE_REQUEST
|
||||||
|
#define MS_PACKET_SAVE_REQUEST
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <sys/un.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include <msgba/client_connection_data.h>
|
||||||
|
|
||||||
|
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
|
43
include/msgba/packet/save_response.h
Normal file
43
include/msgba/packet/save_response.h
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
#ifndef MS_PACKET_SAVE_RESPONSE
|
||||||
|
#define MS_PACKET_SAVE_RESPONSE
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
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
|
@ -1,8 +1,9 @@
|
|||||||
#ifndef MS_PACKET_SEND_HELLO
|
#ifndef MS_PACKET_SEND_FRAME
|
||||||
#define MS_PACKET_SEND_HELLO
|
#define MS_PACKET_SEND_FRAME
|
||||||
#include <msgba/core_controller.h>
|
#include <stdint.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
struct msPacket;
|
struct msPacket;
|
||||||
|
typedef uint32_t color_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Structure representing a video frame packet.
|
* Structure representing a video frame packet.
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#ifndef MS_PLAYER
|
#ifndef MS_PLAYER
|
||||||
#define MS_PLAYER
|
#define MS_PLAYER
|
||||||
|
#include <linux/limits.h>
|
||||||
#include <mgba/flags.h>
|
#include <mgba/flags.h>
|
||||||
#include <mgba/core/core.h>
|
#include <mgba/core/core.h>
|
||||||
#include <mgba/core/thread.h>
|
#include <mgba/core/thread.h>
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
project('tech.owlcode.msgba', 'c')
|
project('tech.owlcode.msgba', 'c')
|
||||||
|
add_global_arguments('-std=c11', '-D_DEFAULT_SOURCE', language : 'c')
|
||||||
|
|
||||||
inc = include_directories('include')
|
inc = include_directories('include')
|
||||||
|
|
||||||
@ -11,6 +12,8 @@ sources = [
|
|||||||
'src/packet/hello.c',
|
'src/packet/hello.c',
|
||||||
'src/packet/send_frame.c',
|
'src/packet/send_frame.c',
|
||||||
'src/packet/key_down.c',
|
'src/packet/key_down.c',
|
||||||
|
'src/packet/save_request.c',
|
||||||
|
'src/packet/save_response.c',
|
||||||
'src/client_connection_data.c',
|
'src/client_connection_data.c',
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -19,7 +22,8 @@ inc = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
link_arguments = [
|
link_arguments = [
|
||||||
'-lmgba'
|
'-lmgba',
|
||||||
|
'-lpthread'
|
||||||
]
|
]
|
||||||
|
|
||||||
executable('msgba',
|
executable('msgba',
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include <msgba/core_controller.h>
|
#include <msgba/core_controller.h>
|
||||||
#include <msgba/client_connection_data.h>
|
#include <msgba/client_connection_data.h>
|
||||||
|
#include <msgba/packet/save_request.h>
|
||||||
|
|
||||||
struct msClientConnectionData *
|
struct msClientConnectionData *
|
||||||
msClientConnectionDataNew(size_t numberOfThread, int clientFd) {
|
msClientConnectionDataNew(size_t numberOfThread, int clientFd) {
|
||||||
@ -11,9 +12,13 @@ msClientConnectionDataNew(size_t numberOfThread, int clientFd) {
|
|||||||
data->coreController = NULL;
|
data->coreController = NULL;
|
||||||
data->mutexSendPacket = malloc(sizeof *data->mutexSendPacket);
|
data->mutexSendPacket = malloc(sizeof *data->mutexSendPacket);
|
||||||
data->mutexPressKey = malloc(sizeof *data->mutexPressKey);
|
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);
|
data->lastFrameDate = calloc(sizeof *data->lastFrameDate, 1);
|
||||||
pthread_mutex_init(data->mutexSendPacket, NULL);
|
pthread_mutex_init(data->mutexSendPacket, NULL);
|
||||||
pthread_mutex_init(data->mutexPressKey, NULL);
|
pthread_mutex_init(data->mutexPressKey, NULL);
|
||||||
|
pthread_mutex_init(data->mutexSaveRequests, NULL);
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -24,10 +29,19 @@ msClientConnectionDataDestroy(struct msClientConnectionData **data) {
|
|||||||
}
|
}
|
||||||
pthread_mutex_destroy((*data)->mutexSendPacket);
|
pthread_mutex_destroy((*data)->mutexSendPacket);
|
||||||
pthread_mutex_destroy((*data)->mutexPressKey);
|
pthread_mutex_destroy((*data)->mutexPressKey);
|
||||||
|
pthread_mutex_destroy((*data)->mutexSaveRequests);
|
||||||
free((*data)->mutexSendPacket);
|
free((*data)->mutexSendPacket);
|
||||||
free((*data)->mutexPressKey);
|
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)->mutexSendPacket = NULL;
|
||||||
(*data)->mutexPressKey = NULL;
|
(*data)->mutexPressKey = NULL;
|
||||||
|
(*data)->mutexSaveRequests = NULL;
|
||||||
free(*data);
|
free(*data);
|
||||||
*data = NULL;
|
*data = NULL;
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
#include <linux/limits.h>
|
||||||
|
|
||||||
#include <mgba/flags.h>
|
#include <mgba/flags.h>
|
||||||
#include <mgba/core/core.h>
|
#include <mgba/core/core.h>
|
||||||
#include <mgba/core/thread.h>
|
#include <mgba/core/thread.h>
|
||||||
@ -85,7 +87,7 @@ mCoreThreadAfterStart(struct mCoreThread *threadContext) {
|
|||||||
struct msClientConnectionData *data = (struct msClientConnectionData *)threadContext->userData;
|
struct msClientConnectionData *data = (struct msClientConnectionData *)threadContext->userData;
|
||||||
struct msCoreController *coreController = data->coreController;
|
struct msCoreController *coreController = data->coreController;
|
||||||
struct mCore *core = coreController->threadContext.core;
|
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");
|
fprintf(stderr, "Unable to load save state\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
#include <linux/limits.h>
|
||||||
|
|
||||||
#include <mgba/flags.h>
|
#include <mgba/flags.h>
|
||||||
#include <mgba/core/core.h>
|
#include <mgba/core/core.h>
|
||||||
#include <mgba/core/thread.h>
|
#include <mgba/core/thread.h>
|
||||||
|
45
src/packet.c
45
src/packet.c
@ -4,23 +4,28 @@
|
|||||||
#include <msgba/packet.h>
|
#include <msgba/packet.h>
|
||||||
#include <msgba/packet/hello.h>
|
#include <msgba/packet/hello.h>
|
||||||
#include <msgba/packet/key_down.h>
|
#include <msgba/packet/key_down.h>
|
||||||
|
#include <msgba/packet/save_request.h>
|
||||||
|
|
||||||
#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 clientFd,
|
||||||
struct msClientConnectionData *const data) {
|
struct msClientConnectionData *const data) {
|
||||||
bool result = false;
|
bool result = false;
|
||||||
printf("Received packet %lu\n", packet->id);
|
printf("Received packet %lu\n", packet->id);
|
||||||
switch (packet->id) {
|
switch (packet->id) {
|
||||||
case PACKET_GET_HELLO:
|
case PACKET_GET_HELLO:
|
||||||
PRINT_DEBUG(PACKET_HELLO, client_fd);
|
PRINT_DEBUG(PACKET_HELLO, clientFd);
|
||||||
result = msPacketHelloGet(packet, client_fd, data);
|
result = msPacketHelloGet(packet, clientFd, data);
|
||||||
break;
|
break;
|
||||||
case PACKET_GET_KEY_DOWN:
|
case PACKET_GET_KEY_DOWN:
|
||||||
PRINT_DEBUG(PACKET_KEY_DOWN, client_fd);
|
PRINT_DEBUG(PACKET_KEY_DOWN, clientFd);
|
||||||
result = msPacketKeyDownGet(packet, client_fd, data);
|
result = msPacketKeyDownGet(packet, clientFd, data);
|
||||||
|
break;
|
||||||
|
case PACKET_GET_SAVE_REQUEST:
|
||||||
|
PRINT_DEBUG(PACKET_SAVE_REQUEST, clientFd);
|
||||||
|
result = msPacketSaveRequestGet(packet, clientFd, data);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
@ -61,7 +66,7 @@ msPacketSend(const struct msPacket *const packet, struct msClientConnectionData
|
|||||||
if (!msPacketWrite(fd, (const void *)&size, sizeof packet->size)) {
|
if (!msPacketWrite(fd, (const void *)&size, sizeof packet->size)) {
|
||||||
goto return_ms_packet_send;
|
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;
|
goto return_ms_packet_send;
|
||||||
}
|
}
|
||||||
result = true;
|
result = true;
|
||||||
@ -71,52 +76,52 @@ return_ms_packet_send:
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct msPacket *
|
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);
|
struct msPacket *packet = malloc(sizeof *packet);
|
||||||
packet->id = id;
|
packet->id = id;
|
||||||
packet->size = size;
|
packet->size = size;
|
||||||
packet->raw_data = raw_data;
|
packet->rawData = rawData;
|
||||||
return packet;
|
return packet;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
msPacketDestroy(struct msPacket **packet) {
|
msPacketDestroy(struct msPacket **packet) {
|
||||||
if ((*packet)->raw_data) {
|
if ((*packet)->rawData) {
|
||||||
free((*packet)->raw_data);
|
free((*packet)->rawData);
|
||||||
}
|
}
|
||||||
free(*packet);
|
free(*packet);
|
||||||
*packet=NULL;
|
*packet=NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct msPacket *
|
struct msPacket *
|
||||||
msPacketRead(int client_fd) {
|
msPacketRead(int clientFd) {
|
||||||
struct msPacket *packet = NULL;
|
struct msPacket *packet = NULL;
|
||||||
size_t id = 0;
|
size_t id = 0;
|
||||||
size_t size = 0;
|
size_t size = 0;
|
||||||
ssize_t result;
|
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) {
|
if (result < sizeof id) {
|
||||||
printf("Unable to read id\n");
|
printf("Unable to read id\n");
|
||||||
goto return_read_packet;
|
goto return_read_packet;
|
||||||
}
|
}
|
||||||
id = be64toh(id);
|
id = be64toh(id);
|
||||||
result = read(client_fd, &size, sizeof size);
|
result = read(clientFd, &size, sizeof size);
|
||||||
if (result < sizeof size) {
|
if (result < sizeof size) {
|
||||||
printf("Unable to read packet\n");
|
printf("Unable to read packet\n");
|
||||||
goto return_read_packet;
|
goto return_read_packet;
|
||||||
}
|
}
|
||||||
size = be64toh(size);
|
size = be64toh(size);
|
||||||
|
|
||||||
raw_data = malloc(size);
|
rawData = malloc(size);
|
||||||
|
|
||||||
size_t to_read_size = size;
|
size_t to_read_size = size;
|
||||||
while (to_read_size > 0) {
|
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) {
|
if (result == -1) {
|
||||||
printf("Unable to read raw_data\n");
|
printf("Unable to read rawData\n");
|
||||||
goto return_read_packet;
|
goto return_read_packet;
|
||||||
}
|
}
|
||||||
to_read_size -= result;
|
to_read_size -= result;
|
||||||
@ -126,10 +131,10 @@ msPacketRead(int client_fd) {
|
|||||||
packet = calloc (1, sizeof *packet);
|
packet = calloc (1, sizeof *packet);
|
||||||
packet->id = id;
|
packet->id = id;
|
||||||
packet->size = size;
|
packet->size = size;
|
||||||
packet->raw_data = raw_data;
|
packet->rawData = rawData;
|
||||||
return_read_packet:
|
return_read_packet:
|
||||||
if (!packet && raw_data) {
|
if (!packet && rawData) {
|
||||||
free(raw_data);
|
free(rawData);
|
||||||
}
|
}
|
||||||
return packet;
|
return packet;
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,11 @@
|
|||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <endian.h>
|
||||||
|
#include <linux/limits.h>
|
||||||
|
|
||||||
#include <sys/signal.h>
|
#include <sys/signal.h>
|
||||||
|
|
||||||
|
#include <mgba/core/core.h>
|
||||||
#include <mgba/core/serialize.h>
|
#include <mgba/core/serialize.h>
|
||||||
|
|
||||||
#include <msgba/packet/send_frame.h>
|
#include <msgba/packet/send_frame.h>
|
||||||
@ -30,13 +33,8 @@ msThreadCallbackStart(struct mCoreThread *threadContext) {
|
|||||||
sigemptyset(&set);
|
sigemptyset(&set);
|
||||||
sigaddset(&set, SIGPIPE);
|
sigaddset(&set, SIGPIPE);
|
||||||
pthread_sigmask(SIG_BLOCK, &set, NULL);
|
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
|
void
|
||||||
msThreadCallbackSetFrame(struct mCoreThread *threadContext) {
|
msThreadCallbackSetFrame(struct mCoreThread *threadContext) {
|
||||||
#define SEC_TO_NANO(sec) \
|
#define SEC_TO_NANO(sec) \
|
||||||
@ -45,8 +43,8 @@ msThreadCallbackSetFrame(struct mCoreThread *threadContext) {
|
|||||||
unsigned int stride;
|
unsigned int stride;
|
||||||
color_t *outputBuffer;
|
color_t *outputBuffer;
|
||||||
unsigned width, height;
|
unsigned width, height;
|
||||||
unsigned char *raw_data = NULL;
|
unsigned char *rawData = NULL;
|
||||||
size_t raw_data_len = 0;
|
size_t rawDataLen = 0;
|
||||||
struct msPacketSendFrame *send_frame = NULL;
|
struct msPacketSendFrame *send_frame = NULL;
|
||||||
struct msPacket *packet = NULL;
|
struct msPacket *packet = NULL;
|
||||||
struct timespec current_date;
|
struct timespec current_date;
|
||||||
@ -70,12 +68,12 @@ msThreadCallbackSetFrame(struct mCoreThread *threadContext) {
|
|||||||
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);
|
send_frame = msPacketSendFrameNew(stride, width * height, outputBuffer);
|
||||||
raw_data = msPacketSendFrameSerialize(send_frame, &raw_data_len);
|
rawData = msPacketSendFrameSerialize(send_frame, &rawDataLen);
|
||||||
if (!raw_data) {
|
if (!rawData) {
|
||||||
goto return_ms_thread_callback_set_frame;
|
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);
|
msPacketSend(packet, data);
|
||||||
|
|
||||||
return_ms_thread_callback_set_frame:
|
return_ms_thread_callback_set_frame:
|
||||||
@ -113,7 +111,7 @@ msPacketHelloGet(const struct msPacket *packet, int client_fd,
|
|||||||
struct msPacketHello *hello = NULL;
|
struct msPacketHello *hello = NULL;
|
||||||
unsigned char *rom = NULL;
|
unsigned char *rom = NULL;
|
||||||
unsigned char *savestate = NULL;
|
unsigned char *savestate = NULL;
|
||||||
FILE *fp = fmemopen(packet->raw_data, packet->size, "r");
|
FILE *fp = fmemopen(packet->rawData, packet->size, "r");
|
||||||
if (!fp) {
|
if (!fp) {
|
||||||
printf("Unable to fmemopen\n");
|
printf("Unable to fmemopen\n");
|
||||||
goto return_get_packet_hello;
|
goto return_get_packet_hello;
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include <mgba/core/input.h>
|
#include <mgba/core/input.h>
|
||||||
|
#include <mgba/core/core.h>
|
||||||
|
|
||||||
#include <msgba/packet.h>
|
#include <msgba/packet.h>
|
||||||
#include <msgba/core_controller.h>
|
#include <msgba/core_controller.h>
|
||||||
@ -13,7 +14,7 @@ msPacketKeyDownGet(const struct msPacket *packet, int clientFd, struct msClientC
|
|||||||
struct msPacketKeyDown *keyDown = NULL;
|
struct msPacketKeyDown *keyDown = NULL;
|
||||||
int key = 0;
|
int key = 0;
|
||||||
char isPressed = 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)) {
|
if (1 != fread(&isPressed, sizeof isPressed, 1, fp)) {
|
||||||
goto return_ms_packet_key_down_get;
|
goto return_ms_packet_key_down_get;
|
||||||
}
|
}
|
||||||
|
178
src/packet/save_request.c
Normal file
178
src/packet/save_request.c
Normal file
@ -0,0 +1,178 @@
|
|||||||
|
#include <pthread.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <mgba/core/serialize.h>
|
||||||
|
#include <mgba/core/core.h>
|
||||||
|
#include <mgba-util/vfs.h>
|
||||||
|
|
||||||
|
#include <msgba/packet.h>
|
||||||
|
#include <msgba/packet/save_request.h>
|
||||||
|
#include <msgba/packet/save_response.h>
|
||||||
|
#include <msgba/core_controller.h>
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
49
src/packet/save_response.c
Normal file
49
src/packet/save_response.c
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include <msgba/packet/save_response.h>
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
@ -1,3 +1,4 @@
|
|||||||
|
#include <stdio.h>
|
||||||
#include <endian.h>
|
#include <endian.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user