107 lines
3.6 KiB
C
107 lines
3.6 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");
|
|
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);
|
|
}
|
|
}
|