msgba/src/main.c

107 lines
3.7 KiB
C

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <mgba/flags.h>
#include <mgba/core/core.h>
#include <mgba/core/thread.h>
#include <mgba/core/interface.h>
#ifdef M_CORE_GBA
#include <mgba/internal/gba/sio/lockstep.h>
#endif
#ifdef M_CORE_GB
#include <mgba/internal/gb/sio/lockstep.h>
#endif
#include <mgba/core/serialize.h>
#include <mgba-util/vfs.h>
#include <msgba/core_controller.h>
#include <msgba/client_connection_data.h>
#include <msgba/global.h>
#include <msgba/packet.h>
char *ms_last_error = "";
#define MAX_NUMBER_OF_THREADS 100
pthread_t pthread_client_connections[MAX_NUMBER_OF_THREADS];
pthread_cond_t cond_client_number_decreased;
pthread_mutex_t mutex_number_connections;
size_t connected_clients = 0;
size_t number_of_threads = 0;
void *handleClientConnection(void *user_data) {
struct msClientConnectionData *data = (struct msClientConnectionData *) user_data;
int client_fd = data->clientFd;
size_t number_of_thread = data->numberOfThread;
struct msPacket *packet = NULL;
printf("Connection from client with id %lu and fd %d\n", number_of_thread, client_fd);
while ((packet = msPacketRead(client_fd)) != NULL) {
bool success = msPacketHandle(packet, client_fd, data);
msPacketDestroy(&packet);
if (!success) {
fprintf(stderr, "Failed handling packet for client_fd %d, closing connection\n", client_fd);
break;
}
}
msClientConnectionDataDestroy(&data);
if (close (client_fd) == 1) {
fprintf(stderr, "Error closing socket %d\n", client_fd);
}
printf("Closing connection with id %lu and fd %d\n", number_of_thread, client_fd);
pthread_mutex_lock(&mutex_number_connections);
connected_clients--;
pthread_mutex_unlock(&mutex_number_connections);
pthread_cond_signal(&cond_client_number_decreased);
return NULL;
}
#define SOCKET_ADDRESS "msgba.sock"
#define BACKLOG 5
int main(int argc, char **argv) {
struct sockaddr_un address;
memset (&address, 0, sizeof address);
address.sun_family = AF_UNIX;
unlink(SOCKET_ADDRESS);
size_t max_size_sun_path = sizeof address.sun_path - 1;
if (strlen(SOCKET_ADDRESS) > max_size_sun_path) {
fprintf(stderr, "Too big socket address\n");
exit (2);
}
strncpy(address.sun_path, SOCKET_ADDRESS, max_size_sun_path);
int fd = socket(AF_UNIX, SOCK_STREAM, 0);
if (fd == -1) {
fprintf (stderr, "Unable to create socket\n");
exit (1);
}
if (bind (fd, (struct sockaddr *)&address,
strlen (SOCKET_ADDRESS) + sizeof (address.sun_family)) == -1) {
fprintf(stderr, "Unable to bind socket\n");
exit (1);
}
if (listen (fd, BACKLOG) == -1) {
fprintf(stderr, "Unable to listen in socket\n");
exit (1);
}
pthread_cond_init(&cond_client_number_decreased, NULL);
pthread_mutex_init(&mutex_number_connections, NULL);
while (1) {
int client_fd = accept(fd, NULL, NULL);
pthread_attr_t attributes;
pthread_attr_init(&attributes);
pthread_attr_setdetachstate(&attributes, 1);
pthread_mutex_lock(&mutex_number_connections);
while (connected_clients == MAX_NUMBER_OF_THREADS) {
pthread_cond_wait(&cond_client_number_decreased, &mutex_number_connections);
}
connected_clients++;
pthread_mutex_unlock(&mutex_number_connections);
struct msClientConnectionData *data = msClientConnectionDataNew(number_of_threads, client_fd);
pthread_create(&pthread_client_connections[connected_clients], &attributes,
&handleClientConnection, (void *)data);
}
}