From e16f061a715eb0d49a4872f7cc8c7bb58bb6e888 Mon Sep 17 00:00:00 2001 From: cbdev Date: Fri, 31 May 2019 22:10:15 +0200 Subject: Unix socket peer connection --- network.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- network.h | 1 + plugin.c | 4 ++-- websocksy.c | 23 +++++++++++++---------- websocksy.h | 5 ++--- 5 files changed, 74 insertions(+), 17 deletions(-) diff --git a/network.c b/network.c index 2ecee4b..34baf8a 100644 --- a/network.c +++ b/network.c @@ -2,6 +2,7 @@ #include #include +#include #include #include #include @@ -10,8 +11,8 @@ #include /* - * Create a file descriptor connected to a socket peer. - * Client sockets will be connected, listening sockets will be bound. + * Create a file descriptor connected to a network socket peer. + * Client sockets will be connected, listening sockets will be bound/listened. * Returns -1 in case of failure, a valid fd otherwise. */ int network_socket(char* host, char* port, int socktype, int listener){ @@ -97,6 +98,59 @@ int network_socket(char* host, char* port, int socktype, int listener){ return fd; } +/* + * Create a file descriptor connected to a unix socket peer. + * Client sockets will be connected, listening sockets will be bound. + * Returns -1 in case of failure, a valid fd otherwise. + */ +int network_socket_unix(char* path, int socktype, int listener){ + struct sockaddr_un addr = { + .sun_family = AF_UNIX, + }; + int fd = socket(AF_UNIX, socktype, 0), flags; + + if(fd < 0){ + fprintf(stderr, "Failed to create socket: %s\n", strerror(errno)); + return -1; + } + + //set nonblocking + flags = fcntl(fd, F_GETFL, 0); + if(fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0){ + fprintf(stderr, "Failed to set socket nonblocking: %s\n", strerror(errno)); + close(fd); + return -1; + } + + strncpy(addr.sun_path, path, (strlen(path) < (sizeof(addr.sun_path) - 1)) ? strlen(path) : (sizeof(addr.sun_path) - 1)); + + if(listener){ + unlink(path); + if(bind(fd, (struct sockaddr*) &addr, sizeof(addr))){ + fprintf(stderr, "Failed to bind: %s\n", strerror(errno)); + close(fd); + return -1; + } + + if(listen(fd, SOMAXCONN)){ + fprintf(stderr, "Failed to listen: %s\n", strerror(errno)); + close(fd); + return -1; + } + + return fd; + } + + //connect clients + if(connect(fd, (struct sockaddr*) &addr, sizeof(addr))){ + fprintf(stderr, "Failed to connect: %s\n", strerror(errno)); + close(fd); + return -1; + } + + return fd; +} + /* * Send arbitrary data over multiple writes if necessary. * Returns 0 on success diff --git a/network.h b/network.h index 50c8e18..9a1cfee 100644 --- a/network.h +++ b/network.h @@ -3,5 +3,6 @@ /* Socket interface convenience functions */ int network_socket(char* host, char* port, int socktype, int listener); +int network_socket_unix(char* path, int socktype, int listener); int network_send(int fd, uint8_t* data, size_t length); int network_send_str(int fd, char* data); diff --git a/plugin.c b/plugin.c index 8b61ec3..87c9bde 100644 --- a/plugin.c +++ b/plugin.c @@ -10,12 +10,12 @@ static char** framing_function_name = NULL; int plugin_framing_load(char* path){ //TODO load plugins - return 1; + return 0; } int plugin_backend_load(char* backend_requested, ws_backend* backend){ //TODO load backend - return 1; + return 0; } int plugin_register_framing(char* name, ws_framing func){ diff --git a/websocksy.c b/websocksy.c index 4846945..1bd1abf 100644 --- a/websocksy.c +++ b/websocksy.c @@ -113,7 +113,11 @@ static peer_transport client_detect_transport(char* host){ } else if(!strncmp(host, "unix://", 8)){ memmove(host, host + 8, strlen(host) - 7); - return peer_unix; + return peer_unix_stream; + } + else if(!strncmp(host, "unix-dgram://", 13)){ + memmove(host, host + 13, strlen(host) - 12); + return peer_unix_dgram; } fprintf(stderr, "Peer address %s does not include any known protocol identifier, guessing tcp_client\n", host); @@ -123,7 +127,8 @@ static peer_transport client_detect_transport(char* host){ /* Establish peer connection for negotiated websocket */ int client_connect(websocket* ws){ ws->peer = config.backend.query(ws->request_path, ws->protocols, ws->protocol, ws->headers, ws->header, ws); - if(!ws->peer.host || !ws->peer.port){ + if(!ws->peer.host){ + //TODO check port if network socket //no peer provided return 1; } @@ -146,19 +151,17 @@ int client_connect(websocket* ws){ case peer_udp_client: ws->peer_fd = network_socket(ws->peer.host, ws->peer.port, SOCK_DGRAM, 0); break; - case peer_tcp_server: - //TODO implement tcp server mode - fprintf(stderr, "TCP Server mode not yet implemented\n"); - return 1; - case peer_udp_server: - ws->peer_fd = network_socket(ws->peer.host, ws->peer.port, SOCK_DGRAM, 1); - break; case peer_fifo_tx: case peer_fifo_rx: - case peer_unix: //TODO implement other peer modes fprintf(stderr, "Peer connection mode not yet implemented\n"); return 1; + case peer_unix_stream: + ws->peer_fd = network_socket_unix(ws->peer.host, SOCK_STREAM, 0); + break; + case peer_unix_dgram: + ws->peer_fd = network_socket_unix(ws->peer.host, SOCK_DGRAM, 0); + break; default: fprintf(stderr, "Invalid peer transport selected\n"); return 1; diff --git a/websocksy.h b/websocksy.h index 9cf1588..8b85719 100644 --- a/websocksy.h +++ b/websocksy.h @@ -92,11 +92,10 @@ typedef enum { peer_transport_detect, peer_tcp_client, peer_udp_client, - peer_tcp_server, - peer_udp_server, peer_fifo_tx, peer_fifo_rx, - peer_unix + peer_unix_stream, + peer_unix_dgram } peer_transport; /* Peer address model */ -- cgit v1.2.3