I am getting AWFULLY close to being able to run this code

This commit is contained in:
XANTRONIX Development 2020-06-20 19:37:03 -04:00 committed by XANTRONIX Industrial
parent 116f4f9f6b
commit c4fa41dab4
8 changed files with 439 additions and 77 deletions

View file

@ -2,7 +2,7 @@
#define _PATTY_AX25_CALL_H
enum patty_ax25_call {
PATTY_AX25_CALL_UNKNOWN,
PATTY_AX25_CALL_NONE,
PATTY_AX25_CALL_SOCKET,
PATTY_AX25_CALL_BIND,
PATTY_AX25_CALL_LISTEN,
@ -10,7 +10,8 @@ enum patty_ax25_call {
PATTY_AX25_CALL_CONNECT,
PATTY_AX25_CALL_CLOSE,
PATTY_AX25_CALL_SENDTO,
PATTY_AX25_CALL_RECVFROM
PATTY_AX25_CALL_RECVFROM,
PATTY_AX25_CALL_COUNT
};
/*

View file

@ -11,6 +11,8 @@
#define PATTY_AX25_IF_OPT_TYPE(n) \
((n) & PATTY_AX25_IF_OPT_TYPE_MASK)
#define PATTY_AX25_IF_BUFSZ 4096
enum patty_ax25_if_type {
PATTY_AX25_IF_UNKNOWN,
PATTY_AX25_IF_KISS_TNC,
@ -31,6 +33,9 @@ typedef struct _patty_ax25_if {
char name[8];
void *rx_buf;
size_t rx_bufsz;
patty_kiss_tnc *tnc;
patty_list *addrs;
} patty_ax25_if;
@ -48,4 +53,11 @@ int patty_ax25_if_add_addr(patty_ax25_if *iface,
int patty_ax25_if_delete_addr(patty_ax25_if *iface,
const char *callsign, uint8_t ssid);
ssize_t patty_ax25_if_recv(patty_ax25_if *iface,
void **buf);
ssize_t patty_ax25_if_send(patty_ax25_if *iface,
const void *buf,
size_t len);
#endif /* _PATTY_AX25_IF_H */

View file

@ -1,13 +1,14 @@
#ifndef _PATTY_AX25_SERVER_H
#define _PATTY_AX25_SERVER_H
#define PATTY_AX25_SERVER_PATH "/var/run/patty/patty.sock"
#define PATTY_AX25_SERVER_CLIENT_PATH_FORMAT "/var/run/patty/%d.sock"
typedef struct _patty_ax25_server patty_ax25_server;
int patty_ax25_server_init(patty_ax25_server *server);
void patty_ax25_server_stop(patty_ax25_server *server);
int patty_ax25_server_run(patty_ax25_server *server);
void patty_ax25_server_destroy(patty_ax25_server *server);
int patty_ax25_server_add_if(patty_ax25_server *server,
patty_ax25_if *iface);
@ -22,4 +23,6 @@ int patty_ax25_server_each_if(patty_ax25_server *server,
int (*callback)(patty_ax25_if *, void *),
void *ctx);
int patty_ax25_server_run(patty_ax25_server *server);
#endif /* _PATTY_AX25_SERVER_H */

View file

@ -29,13 +29,14 @@ patty_dict *patty_dict_new();
patty_dict_slot *patty_dict_slot_find(patty_dict *dict, uint32_t hash);
typedef int (*patty_dict_callback)(
void * key,
size_t keysz,
void * value,
void * ctx);
typedef int (*patty_dict_callback)(void *key,
size_t keysz,
void *value,
void *ctx);
int patty_dict_each(patty_dict *dict, patty_dict_callback callback, void *ctx);
int patty_dict_each(patty_dict *dict,
patty_dict_callback callback,
void *ctx);
void *patty_dict_get(patty_dict *dict, void *key, size_t keysz);

View file

@ -59,9 +59,8 @@ void patty_list_reset(patty_list_iterator *iterator);
void patty_list_finish(patty_list_iterator *iterator);
void patty_list_each(
patty_list * list,
patty_list_callback callback,
void * ctx);
void patty_list_each(patty_list *list,
patty_list_callback callback,
void *ctx);
#endif /* _PATTY_LIST_H */

View file

@ -6,7 +6,7 @@
int patty_ax25_call_socket(int server,
int type) {
int call = PATTY_AX25_CALL_SOCKET;
enum patty_ax25_call call = PATTY_AX25_CALL_SOCKET;
patty_ax25_call_socket_request request = {
type
@ -37,7 +37,7 @@ error_io:
int patty_ax25_call_bind(int server,
int socket,
patty_ax25_addr *peer) {
int call = PATTY_AX25_CALL_BIND;
enum patty_ax25_call call = PATTY_AX25_CALL_BIND;
patty_ax25_call_bind_request request = {
socket
@ -69,7 +69,7 @@ error_io:
int patty_ax25_call_listen(int server,
int socket) {
int call = PATTY_AX25_CALL_LISTEN;
enum patty_ax25_call call = PATTY_AX25_CALL_LISTEN;
patty_ax25_call_listen_request request = {
socket
@ -101,7 +101,7 @@ int patty_ax25_call_accept(int server,
int socket,
patty_ax25_addr *peer,
char *path) {
int call = PATTY_AX25_CALL_ACCEPT;
enum patty_ax25_call call = PATTY_AX25_CALL_ACCEPT;
patty_ax25_call_accept_request request = {
socket
@ -138,7 +138,7 @@ int patty_ax25_call_connect(int server,
int socket,
patty_ax25_addr *peer,
char *path) {
int call = PATTY_AX25_CALL_CONNECT;
enum patty_ax25_call call = PATTY_AX25_CALL_CONNECT;
patty_ax25_call_connect_request request = {
socket
@ -174,7 +174,7 @@ error_io:
int patty_ax25_call_close(int server,
int socket) {
int call = PATTY_AX25_CALL_CLOSE;
enum patty_ax25_call call = PATTY_AX25_CALL_CLOSE;
patty_ax25_call_close_request request = {
socket

121
src/if.c
View file

@ -5,17 +5,9 @@
#include <patty/ax25.h>
static patty_ax25_if *create_tnc(const char *device) {
patty_ax25_if *iface;
static char * prefix = "kiss";
static int number = 0;
if ((iface = malloc(sizeof(*iface))) == NULL) {
goto error_malloc_iface;
}
memset(iface, '\0', sizeof(*iface));
static int init_tnc(patty_ax25_if *iface, const char *device) {
static char *prefix = "kiss";
static int number = 0;
if ((iface->tnc = patty_kiss_tnc_open(device)) == NULL) {
goto error_kiss_tnc_open;
@ -25,58 +17,79 @@ static patty_ax25_if *create_tnc(const char *device) {
snprintf(iface->name, sizeof(iface->name), "%s%d", prefix, number++);
return iface;
return 0;
error_kiss_tnc_open:
free(iface);
error_malloc_iface:
return NULL;
return -1;
}
static void destroy_tnc(patty_ax25_if *iface) {
static void close_tnc(patty_ax25_if *iface) {
patty_kiss_tnc_close(iface->tnc);
}
patty_ax25_if *patty_ax25_if_create(int opts, void *info) {
patty_ax25_if *iface;
switch (PATTY_AX25_IF_OPT_TYPE(opts)) {
case PATTY_AX25_IF_KISS_TNC: {
iface = create_tnc((const char *)info);
break;
}
default: {
errno = EINVAL;
goto error;
}
if ((iface = malloc(sizeof(*iface))) == NULL) {
goto error_malloc_iface;
}
if (iface == NULL) {
goto error;
memset(iface, '\0', sizeof(*iface));
if ((iface->rx_buf = malloc(PATTY_AX25_IF_BUFSZ)) == NULL) {
goto error_malloc_rx_buf;
} else {
iface->rx_bufsz = PATTY_AX25_IF_BUFSZ;
}
if ((iface->addrs = patty_list_new()) == NULL) {
goto error;
goto error_list_new;
}
switch (PATTY_AX25_IF_OPT_TYPE(opts)) {
case PATTY_AX25_IF_KISS_TNC:
if (init_tnc(iface, (const char *)info) < 0) {
goto error_init;
}
break;
default:
errno = EINVAL;
goto error_invalid_if_type;
}
return iface;
error:
error_invalid_if_type:
error_init:
patty_list_destroy(iface->addrs);
error_list_new:
free(iface->rx_buf);
error_malloc_rx_buf:
free(iface);
error_malloc_iface:
return NULL;
}
void patty_ax25_if_destroy(patty_ax25_if *iface) {
switch (iface->type) {
case PATTY_AX25_IF_KISS_TNC: {
destroy_tnc(iface); break;
}
case PATTY_AX25_IF_KISS_TNC:
close_tnc(iface);
break;
default: break;
default:
break;
}
patty_list_destroy(iface->addrs);
free(iface->rx_buf);
free(iface);
}
int patty_ax25_if_each_addr(patty_ax25_if *iface,
@ -221,3 +234,37 @@ error_ntop:
return -1;
}
ssize_t patty_ax25_if_recv(patty_ax25_if *iface,
void **buf) {
ssize_t readlen;
int port;
if ((readlen = patty_kiss_tnc_recv(iface->tnc,
iface->rx_buf,
iface->rx_bufsz,
&port)) < 0) {
goto error_kiss_tnc_recv;
}
*buf = iface->rx_buf;
return readlen;
error_kiss_tnc_recv:
return -1;
}
ssize_t patty_ax25_if_send(patty_ax25_if *iface,
const void *buf,
size_t len) {
ssize_t wrlen;
if ((wrlen = patty_kiss_tnc_send(iface->tnc, buf, len, 0)) < 0) {
goto error_kiss_tnc_send;
}
return wrlen;
error_kiss_tnc_send:
return -1;
}

View file

@ -10,7 +10,20 @@
#include <patty/ax25.h>
typedef int (*patty_ax25_server_call)(patty_ax25_server *, int);
struct _patty_ax25_server {
int fd, /* fd of UNIX domain socket */
fd_max;
struct timeval timeout;
fd_set fds_watch, /* fds to monitor with select() */
fds_socks, /* fds belonging to socks */
fds_clients, /* fds belonging to clients */
fds_r, /* fds select()ed for reading */
fds_w; /* fds select()ed for writing */
patty_list *ifaces;
patty_dict *socks_by_fd,
@ -18,13 +31,8 @@ struct _patty_ax25_server {
*socks_pending_connect,
*socks_established;
patty_dict *clients_by_sock;
int fd_max;
fd_set fds_watch, /* fds to monitor with select() */
fds_socks, /* fds belonging to socks */
fds_clients; /* fds belonging to clients */
patty_dict *clients,
*clients_by_sock;
};
int patty_ax25_server_init(patty_ax25_server *server) {
@ -50,6 +58,10 @@ int patty_ax25_server_init(patty_ax25_server *server) {
goto error_dict_new_socks_established;
}
if ((server->clients = patty_dict_new()) == NULL) {
goto error_dict_new_clients;
}
if ((server->clients_by_sock = patty_dict_new()) == NULL) {
goto error_dict_new_clients_by_sock;
}
@ -57,6 +69,9 @@ int patty_ax25_server_init(patty_ax25_server *server) {
return 0;
error_dict_new_clients_by_sock:
patty_dict_destroy(server->clients);
error_dict_new_clients:
patty_dict_destroy(server->socks_established);
error_dict_new_socks_established:
@ -81,17 +96,6 @@ static int destroy_if(patty_ax25_if *iface, void *ctx) {
return 0;
}
void patty_ax25_server_stop(patty_ax25_server *server) {
patty_dict_destroy(server->clients_by_sock);
patty_dict_destroy(server->socks_established);
patty_dict_destroy(server->socks_pending_connect);
patty_dict_destroy(server->socks_pending_accept);
patty_dict_destroy(server->socks_by_fd);
patty_ax25_server_each_if(server, destroy_if, NULL);
patty_list_destroy(server->ifaces);
}
static void sock_init(patty_ax25_sock *sock, enum patty_ax25_sock_type type) {
memset(sock, '\0', sizeof(*sock));
@ -576,7 +580,10 @@ static int server_accept_unix(patty_ax25_server *server,
goto error_socket;
}
if (snprintf(response->path, PATTY_AX25_SOCK_PATH_SIZE, "/var/run/patty/%d.sock", sock->fd) < 0) {
if (snprintf(response->path,
PATTY_AX25_SOCK_PATH_SIZE,
PATTY_AX25_SERVER_CLIENT_PATH_FORMAT,
sock->fd) < 0) {
goto error_snprintf;
}
@ -787,3 +794,295 @@ error_sock_by_fd:
error_io:
return -1;
}
static patty_ax25_server_call server_calls[PATTY_AX25_CALL_COUNT] = {
NULL,
server_socket,
server_bind,
server_listen,
server_accept,
server_connect,
server_close,
NULL,
NULL
};
static int listen_unix(patty_ax25_server *server, const char *path) {
struct sockaddr_un addr;
if (server->fd) {
errno = EBUSY;
goto error_listening;
}
if ((server->fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) {
goto error_socket;
}
memset(&addr, '\0', sizeof(addr));
addr.sun_family = AF_UNIX;
strncpy(addr.sun_path, path, sizeof(addr.sun_path));
if (bind(server->fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
goto error_bind;
}
if (listen(server->fd, 0) < 0) {
goto error_listen;
}
return 0;
error_listen:
error_bind:
close(server->fd);
error_socket:
error_listening:
return -1;
}
static int accept_client(patty_ax25_server *server) {
int fd;
struct sockaddr addr;
socklen_t addrlen;
if (!FD_ISSET(server->fd, &server->fds_r)) {
goto done;
}
if ((fd = accept(server->fd, &addr, &addrlen)) < 0) {
goto error_accept;
}
if (patty_dict_set(server->clients,
NULL + fd,
sizeof(fd),
NULL + fd) == NULL) {
goto error_dict_set;
}
FD_SET(fd, &server->fds_clients);
done:
return 0;
error_dict_set:
close(fd);
error_accept:
return -1;
}
static int handle_client(void *key,
size_t keysz,
void *value,
void *ctx) {
patty_ax25_server *server = ctx;
int client = (int)(key - NULL);
ssize_t readlen;
enum patty_ax25_call call;
if (!FD_ISSET(client, &server->fds_r)) {
goto done;
}
if ((readlen = read(server->fd, &call, sizeof(call))) < 0) {
goto error_io;
} else if (readlen == 0) {
FD_CLR(client, &server->fds_watch);
FD_CLR(client, &server->fds_clients);
if (patty_dict_delete(server->clients,
key,
keysz) < 0) {
goto error_dict_delete;
}
if (close(client) < 0) {
goto error_io;
}
goto done;
}
if (call <= PATTY_AX25_CALL_NONE || call >= PATTY_AX25_CALL_COUNT) {
goto error_io;
}
return server_calls[call](server, client);
done:
return 0;
error_dict_delete:
error_io:
return -1;
}
static int handle_clients(patty_ax25_server *server) {
return patty_dict_each(server->clients, handle_client, server);
}
static int handle_packet_rx(patty_ax25_server *server,
patty_ax25_if *iface,
void *buf,
size_t len) {
patty_ax25_frame frame;
if (patty_ax25_frame_decode(&frame, buf, len) < 0) {
goto error_io;
}
/*
* TODO: Handle inbound packet
*/
return 0;
error_io:
return -1;
}
static int handle_iface(patty_ax25_server *server, patty_ax25_if *iface) {
int fd = patty_kiss_tnc_fd(iface->tnc);
void *buf;
ssize_t readlen;
if (!FD_ISSET(fd, &server->fds_r)) {
goto done;
}
if ((readlen = patty_ax25_if_recv(iface, &buf)) < 0) {
goto error_io;
} else if (readlen == 0) {
FD_CLR(fd, &server->fds_watch);
goto done;
}
if (handle_packet_rx(server, iface, buf, readlen) < 0) {
goto error_io;
}
done:
return 0;
error_io:
return -1;
}
static int handle_ifaces(patty_ax25_server *server) {
patty_list_iterator *iter;
patty_ax25_if *iface;
if ((iter = patty_list_start(server->ifaces)) == NULL) {
goto error_list_start;
}
while ((iface = patty_list_next(iter)) != NULL) {
if (handle_iface(server, iface) < 0) {
goto error_io;
}
}
patty_list_finish(iter);
return 0;
error_io:
patty_list_finish(iter);
error_list_start:
return -1;
}
static int handle_sock(void *key,
size_t keysz,
void *value,
void *ctx) {
patty_ax25_server *server = ctx;
patty_ax25_sock *sock = value;
int fd = (int)(key - NULL);
ssize_t readlen;
if (!FD_ISSET(fd, &server->fds_r)) {
goto done;
}
/*
* TODO: Finish this
*/
done:
return 0;
}
static int handle_socks(patty_ax25_server *server) {
return patty_dict_each(server->socks_by_fd,
handle_sock,
server);
}
int patty_ax25_server_run(patty_ax25_server *server) {
if (listen_unix(server, PATTY_AX25_SERVER_PATH) < 0) {
goto error_listen_unix;
}
while (1) {
int nready;
FD_COPY(&server->fds_watch, &server->fds_r);
FD_COPY(&server->fds_watch, &server->fds_w);
if ((nready = select( server->fd_max,
&server->fds_r,
&server->fds_w,
NULL,
&server->timeout)) < 0) {
goto error_io;
}
if (accept_client(server) < 0) {
goto error_io;
}
if (handle_clients(server) < 0) {
goto error_io;
}
if (handle_ifaces(server) < 0) {
goto error_io;
}
if (handle_socks(server) < 0) {
goto error_io;
}
}
close(server->fd);
return 0;
error_io:
close(server->fd);
error_listen_unix:
return -1;
}
void patty_ax25_server_destroy(patty_ax25_server *server) {
patty_dict_destroy(server->clients_by_sock);
patty_dict_destroy(server->clients);
patty_dict_destroy(server->socks_established);
patty_dict_destroy(server->socks_pending_connect);
patty_dict_destroy(server->socks_pending_accept);
patty_dict_destroy(server->socks_by_fd);
patty_ax25_server_each_if(server, destroy_if, NULL);
patty_list_destroy(server->ifaces);
}