refactor server sockets so they're a bit cleaner
This commit is contained in:
parent
5814e512ba
commit
0c80ea5f10
@ -1,5 +1,6 @@
|
|||||||
// sock.c
|
// sock.c
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <sys/un.h>
|
#include <sys/un.h>
|
||||||
@ -7,6 +8,8 @@
|
|||||||
#include "sock.h"
|
#include "sock.h"
|
||||||
|
|
||||||
enum error_t sock_init(int *sockptr) {
|
enum error_t sock_init(int *sockptr) {
|
||||||
|
assert(sockptr != NULL);
|
||||||
|
|
||||||
int const sock = socket(AF_UNIX, SOCK_STREAM, 0);
|
int const sock = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||||
if (sock < 0) goto sock_init_error;
|
if (sock < 0) goto sock_init_error;
|
||||||
|
|
||||||
|
9
server/src/data.h
Normal file
9
server/src/data.h
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
#ifndef DAEMON_DATA_H
|
||||||
|
#define DAEMON_DATA_H
|
||||||
|
|
||||||
|
struct data_t {
|
||||||
|
int socket;
|
||||||
|
int socket_accept;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
@ -11,15 +11,27 @@
|
|||||||
|
|
||||||
#include "opts.h"
|
#include "opts.h"
|
||||||
#include "sock.h"
|
#include "sock.h"
|
||||||
|
#include "data.h"
|
||||||
|
|
||||||
static void handle_signal(int _) {
|
static void handle_signal(int _) {
|
||||||
remove("/tmp/swd.sock");
|
remove(SOCK_PATH);
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
enum error_t game_loop(struct data_t *data) {
|
||||||
|
char buffer[1024] = { 0 };
|
||||||
|
|
||||||
|
read(data->socket_accept, buffer, 1024);
|
||||||
|
write(data->socket_accept, buffer, 1024);
|
||||||
|
|
||||||
|
return ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
enum error_t err = ERR_OK;
|
enum error_t err = ERR_OK;
|
||||||
|
struct data_t daemon_data = { 0 };
|
||||||
|
|
||||||
signal(SIGINT, handle_signal);
|
signal(SIGINT, handle_signal);
|
||||||
signal(SIGTERM, handle_signal);
|
signal(SIGTERM, handle_signal);
|
||||||
@ -33,35 +45,16 @@ int main(int argc, char **argv) {
|
|||||||
err = opts_init(&options);
|
err = opts_init(&options);
|
||||||
if (err) goto handle_error;
|
if (err) goto handle_error;
|
||||||
|
|
||||||
int sock;
|
err = sock_loop(&daemon_data, game_loop);
|
||||||
err = sock_init(&sock);
|
|
||||||
if (err) goto handle_error;
|
if (err) goto handle_error;
|
||||||
|
|
||||||
// Can I move this into its own function that takes a function pointer?
|
|
||||||
for (int sock_accept; ;) {
|
|
||||||
sock_accept = accept(sock, NULL, NULL);
|
|
||||||
if (sock_accept < 0) { err = ERR_SOCKET; goto handle_error_socket; }
|
|
||||||
|
|
||||||
char ibuf[1028] = { 0 };
|
|
||||||
|
|
||||||
// Just echoing everything back for now
|
|
||||||
read(sock_accept, ibuf, 1028);
|
|
||||||
write(sock_accept, ibuf, 1028);
|
|
||||||
|
|
||||||
close(sock_accept);
|
|
||||||
}
|
|
||||||
|
|
||||||
close(sock);
|
|
||||||
remove("/tmp/swd.sock");
|
|
||||||
opts_free(&options);
|
opts_free(&options);
|
||||||
return ERR_OK;
|
return ERR_OK;
|
||||||
|
|
||||||
handle_error_socket:
|
|
||||||
close(sock);
|
|
||||||
remove("/tmp/swd.sock");
|
|
||||||
handle_error:
|
handle_error:
|
||||||
if (options.daemonise) syslog(LOG_ERR, "%s", ERROR_STRS[err]);
|
if (options.daemonise) syslog(LOG_ERR, "%s", ERROR_STRS[err]);
|
||||||
opts_free(&options);
|
opts_free(&options);
|
||||||
|
|
||||||
handle_error_pre_opts:
|
handle_error_pre_opts:
|
||||||
printf("ERROR: %s\n", ERROR_STRS[err]);
|
printf("ERROR: %s\n", ERROR_STRS[err]);
|
||||||
return err;
|
return err;
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
// sock.c
|
// sock.c
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
@ -8,26 +9,65 @@
|
|||||||
#include "sock.h"
|
#include "sock.h"
|
||||||
|
|
||||||
enum error_t sock_init(int *sockptr) {
|
enum error_t sock_init(int *sockptr) {
|
||||||
|
assert(sockptr != NULL);
|
||||||
|
|
||||||
int const sock = socket(AF_UNIX, SOCK_STREAM, 0);
|
int const sock = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||||
if (sock < 0) goto sock_init_error;
|
if (sock < 0) goto sock_init_error;
|
||||||
|
|
||||||
struct sockaddr_un sa = { 0 };
|
struct sockaddr_un sa = { 0 };
|
||||||
sa.sun_family = AF_UNIX;
|
sa.sun_family = AF_UNIX;
|
||||||
strcpy(sa.sun_path, "/tmp/swd.sock");
|
|
||||||
// Socket path should be a shared setting between server and client
|
|
||||||
|
|
||||||
remove("/tmp/swd.sock");
|
strcpy(sa.sun_path, SOCK_PATH);
|
||||||
|
remove(SOCK_PATH);
|
||||||
|
// Should be redundant but it doesn't hurt to be sure
|
||||||
|
|
||||||
if (bind(sock, (struct sockaddr *)&sa, sizeof(sa))) goto sock_error;
|
if (bind(sock, (struct sockaddr *)&sa, sizeof(sa))) goto sock_error;
|
||||||
|
|
||||||
if (listen(sock, 4096) < 0) goto sock_error;
|
if (listen(sock, 4096) < 0) goto sock_error;
|
||||||
|
|
||||||
*sockptr = sock;
|
*sockptr = sock;
|
||||||
return ERR_OK;
|
return ERR_OK;
|
||||||
|
|
||||||
sock_error:
|
sock_error:
|
||||||
close(sock);
|
sock_free(&sock);
|
||||||
remove("/tmp/swd.sock");
|
|
||||||
sock_init_error:
|
sock_init_error:
|
||||||
return ERR_SOCKET;
|
return ERR_SOCKET;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void sock_free(int const *sockptr) {
|
||||||
|
assert(sockptr != NULL);
|
||||||
|
|
||||||
|
close(*sockptr);
|
||||||
|
remove(SOCK_PATH);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
enum error_t sock_loop(struct data_t *data, gameloop_fn fn) {
|
||||||
|
assert(data != NULL);
|
||||||
|
|
||||||
|
enum error_t err = ERR_OK;
|
||||||
|
|
||||||
|
if ((err = sock_init(&data->socket))) return err;
|
||||||
|
|
||||||
|
for (int sock_accept;;) {
|
||||||
|
if ((sock_accept = accept(data->socket, NULL, NULL)) < 0) {
|
||||||
|
err = ERR_SOCKET;
|
||||||
|
goto sock_loop_end_pre;
|
||||||
|
};
|
||||||
|
|
||||||
|
data->socket_accept = sock_accept;
|
||||||
|
if ((err = fn(data))) goto sock_loop_end_pre;
|
||||||
|
|
||||||
|
close(data->socket_accept);
|
||||||
|
continue;
|
||||||
|
|
||||||
|
sock_loop_end_pre:
|
||||||
|
close(data->socket_accept);
|
||||||
|
goto sock_loop_end;
|
||||||
|
}
|
||||||
|
|
||||||
|
sock_loop_end:
|
||||||
|
sock_free(&data->socket);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
@ -3,6 +3,15 @@
|
|||||||
|
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
|
|
||||||
|
#include "data.h"
|
||||||
|
|
||||||
|
#define SOCK_PATH "/tmp/swd.sock"
|
||||||
|
// Socket path should be a shared setting between server and client
|
||||||
|
|
||||||
enum error_t sock_init(int *);
|
enum error_t sock_init(int *);
|
||||||
|
void sock_free(int const *);
|
||||||
|
|
||||||
|
typedef enum error_t (* gameloop_fn)(struct data_t *);;
|
||||||
|
enum error_t sock_loop(struct data_t *, gameloop_fn);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user