Implement SOCK_DGRAM

Implement PATTY_AX25_SOCK_DGRAM type sockets as a means of exchanging UI
frames between stations without requiring calling code to encode and
decode UI frames explicitly
This commit is contained in:
XANTRONIX Development 2020-08-07 18:17:36 -04:00 committed by XANTRONIX Industrial
parent 1d03b2883a
commit 4899aa4796
5 changed files with 89 additions and 45 deletions

View file

@ -59,8 +59,7 @@ enum patty_ax25_frame_type {
PATTY_AX25_FRAME_FRMR = 0x87, PATTY_AX25_FRAME_FRMR = 0x87,
PATTY_AX25_FRAME_UI = 0x03, PATTY_AX25_FRAME_UI = 0x03,
PATTY_AX25_FRAME_XID = 0xaf, PATTY_AX25_FRAME_XID = 0xaf,
PATTY_AX25_FRAME_TEST = 0xe3, PATTY_AX25_FRAME_TEST = 0xe3
PATTY_AX25_FRAME_UNKNOWN = 0xff
}; };
typedef struct _patty_ax25_frame { typedef struct _patty_ax25_frame {

View file

@ -39,6 +39,7 @@
enum patty_ax25_sock_type { enum patty_ax25_sock_type {
PATTY_AX25_SOCK_STREAM, PATTY_AX25_SOCK_STREAM,
PATTY_AX25_SOCK_DGRAM,
PATTY_AX25_SOCK_RAW PATTY_AX25_SOCK_RAW
}; };

View file

@ -184,7 +184,7 @@ ssize_t patty_ax25_frame_decode_control(patty_ax25_frame *frame,
frame->nr = 0; frame->nr = 0;
frame->ns = 0; frame->ns = 0;
frame->pf = 0; frame->pf = 0;
frame->type = PATTY_AX25_FRAME_UNKNOWN; frame->type = 0xff;
frame->proto = PATTY_AX25_PROTO_UNKNOWN; frame->proto = PATTY_AX25_PROTO_UNKNOWN;
frame->info = NULL; frame->info = NULL;
frame->infolen = 0; frame->infolen = 0;

View file

@ -842,8 +842,6 @@ static int server_connect(patty_ax25_server *server,
*/ */
memcpy(&sock->remote, &request.peer, sizeof(request.peer)); memcpy(&sock->remote, &request.peer, sizeof(request.peer));
sock->state = PATTY_AX25_SOCK_PENDING_CONNECT;
if (sock_save_remote(server, sock) < 0) { if (sock_save_remote(server, sock) < 0) {
goto error_sock_save_remote; goto error_sock_save_remote;
} }
@ -852,21 +850,34 @@ static int server_connect(patty_ax25_server *server,
goto error_client_save_by_sock; goto error_client_save_by_sock;
} }
switch (sock->type) {
case PATTY_AX25_SOCK_DGRAM:
sock->state = PATTY_AX25_SOCK_ESTABLISHED;
break;
case PATTY_AX25_SOCK_STREAM:
sock->state = PATTY_AX25_SOCK_PENDING_CONNECT;
/* /*
* Send an XID frame, to attempt to negotiate AX.25 v2.2 and its default * Send an XID frame, to attempt to negotiate AX.25 v2.2 and its
* parameters. * default parameters.
*/ */
if (patty_ax25_sock_send_xid(sock, PATTY_AX25_FRAME_COMMAND) < 0) { if (patty_ax25_sock_send_xid(sock, PATTY_AX25_FRAME_COMMAND) < 0) {
return respond_connect(client, -1, errno); return respond_connect(client, -1, errno);
} }
patty_timer_start(&sock->timer_t1, sock->n_ack);
/* /*
* At this point, we will wait for a DM, FRMR or XID response, which * At this point, we will wait for a DM, FRMR or XID response, which
* will help us determine what version of AX.25 to apply for this socket, * will help us determine what version of AX.25 to apply for this
* or whether the peer is not accepting connections. * socket, or whether the peer is not accepting connections.
*/ */
patty_timer_start(&sock->timer_t1, sock->n_ack);
default:
break;
}
return 0; return 0;
error_client_save_by_sock: error_client_save_by_sock:
@ -1396,6 +1407,17 @@ error_write:
return -1; return -1;
} }
static int handle_ui(patty_ax25_server *server,
patty_ax25_if *iface,
patty_ax25_sock *sock,
patty_ax25_frame *frame) {
if (sock == NULL || sock->type != PATTY_AX25_SOCK_DGRAM) {
return 0;
}
return write(sock->fd, frame->info, frame->infolen);
}
static int handle_disc(patty_ax25_server *server, static int handle_disc(patty_ax25_server *server,
patty_ax25_if *iface, patty_ax25_if *iface,
patty_ax25_sock *sock, patty_ax25_sock *sock,
@ -1690,6 +1712,7 @@ static int handle_frame(patty_ax25_server *server,
switch (frame.type) { switch (frame.type) {
case PATTY_AX25_FRAME_I: return handle_i(server, iface, sock, &frame); case PATTY_AX25_FRAME_I: return handle_i(server, iface, sock, &frame);
case PATTY_AX25_FRAME_UI: return handle_ui(server, iface, sock, &frame);
case PATTY_AX25_FRAME_RR: return handle_rr(server, sock, &frame); case PATTY_AX25_FRAME_RR: return handle_rr(server, sock, &frame);
case PATTY_AX25_FRAME_RNR: return handle_rnr(server, sock, &frame); case PATTY_AX25_FRAME_RNR: return handle_rnr(server, sock, &frame);
case PATTY_AX25_FRAME_REJ: return handle_rej(server, sock, &frame); case PATTY_AX25_FRAME_REJ: return handle_rej(server, sock, &frame);
@ -1702,9 +1725,6 @@ static int handle_frame(patty_ax25_server *server,
case PATTY_AX25_FRAME_DM: return handle_dm(server, iface, sock, &frame); case PATTY_AX25_FRAME_DM: return handle_dm(server, iface, sock, &frame);
case PATTY_AX25_FRAME_DISC: return handle_disc(server, iface, sock, &frame); case PATTY_AX25_FRAME_DISC: return handle_disc(server, iface, sock, &frame);
case PATTY_AX25_FRAME_FRMR: return handle_frmr(server, iface, sock, &frame); case PATTY_AX25_FRAME_FRMR: return handle_frmr(server, iface, sock, &frame);
default:
break;
} }
return 0; return 0;

View file

@ -111,26 +111,28 @@ error_realloc_tx_buf:
return -1; return -1;
} }
static patty_ax25_sock *init_raw(patty_ax25_sock *sock) { static patty_ax25_sock *init_dgram(patty_ax25_sock *sock,
if (bind_pty(sock) < 0) { enum patty_ax25_proto proto) {
goto error_bind_pty; sock->proto = proto;
sock->type = PATTY_AX25_SOCK_DGRAM;
return sock;
} }
static patty_ax25_sock *init_raw(patty_ax25_sock *sock) {
if ((sock->raw = patty_kiss_tnc_new_fd(sock->fd)) == NULL) { if ((sock->raw = patty_kiss_tnc_new_fd(sock->fd)) == NULL) {
goto error_kiss_tnc_new_fd; goto error_kiss_tnc_new_fd;
} }
sock->proto = PATTY_AX25_PROTO_NONE; sock->proto = PATTY_AX25_PROTO_NONE;
sock->type = PATTY_AX25_SOCK_RAW; sock->type = PATTY_AX25_SOCK_RAW;
sock->state = PATTY_AX25_SOCK_ESTABLISHED;
return sock; return sock;
error_kiss_tnc_new_fd: error_kiss_tnc_new_fd:
(void)close(sock->fd); (void)close(sock->fd);
error_bind_pty:
free(sock);
return NULL; return NULL;
} }
@ -144,11 +146,20 @@ patty_ax25_sock *patty_ax25_sock_new(enum patty_ax25_proto proto,
memset(sock, '\0', sizeof(*sock)); memset(sock, '\0', sizeof(*sock));
if (type == PATTY_AX25_SOCK_RAW) { if (bind_pty(sock) < 0) {
return init_raw(sock); goto error_bind_pty;
} }
switch (type) {
case PATTY_AX25_SOCK_DGRAM:
return init_dgram(sock, proto);
case PATTY_AX25_SOCK_RAW:
return init_raw(sock);
case PATTY_AX25_SOCK_STREAM:
patty_ax25_sock_init(sock); patty_ax25_sock_init(sock);
}
sock->proto = proto; sock->proto = proto;
sock->type = type; sock->type = type;
@ -160,18 +171,14 @@ patty_ax25_sock *patty_ax25_sock_new(enum patty_ax25_proto proto,
goto error_init_bufs; goto error_init_bufs;
} }
if (bind_pty(sock) < 0) {
goto error_bind_pty;
}
return sock; return sock;
error_bind_pty:
error_init_bufs: error_init_bufs:
if (sock->tx_slots) free(sock->tx_slots); if (sock->tx_slots) free(sock->tx_slots);
if (sock->rx_buf) free(sock->rx_buf); if (sock->rx_buf) free(sock->rx_buf);
if (sock->tx_buf) free(sock->tx_buf); if (sock->tx_buf) free(sock->tx_buf);
error_bind_pty:
free(sock); free(sock);
error_malloc_sock: error_malloc_sock:
@ -577,6 +584,10 @@ static uint16_t control_i(patty_ax25_sock *sock, int flag) {
} }
} }
static uint16_t control_ui(int flag) {
return PATTY_AX25_FRAME_UI | (flag << 4);
}
static uint16_t control_s(patty_ax25_sock *sock, static uint16_t control_s(patty_ax25_sock *sock,
enum patty_ax25_frame_type type, enum patty_ax25_frame_type type,
int flag) { int flag) {
@ -719,16 +730,14 @@ ssize_t patty_ax25_sock_write(patty_ax25_sock *sock,
size_t len) { size_t len) {
uint16_t control; uint16_t control;
if (sock->type == PATTY_AX25_SOCK_RAW) {
return patty_ax25_if_send(sock->iface, buf, len);
}
if (sock->mode == PATTY_AX25_SOCK_DM) { if (sock->mode == PATTY_AX25_SOCK_DM) {
errno = EBADF; errno = EBADF;
goto error_invalid_mode; goto error_invalid_mode;
} }
switch (sock->type) {
case PATTY_AX25_SOCK_STREAM:
control = control_i(sock, 0); control = control_i(sock, 0);
if (frame_send(sock, PATTY_AX25_FRAME_COMMAND, control, buf, len) < 0) { if (frame_send(sock, PATTY_AX25_FRAME_COMMAND, control, buf, len) < 0) {
@ -737,6 +746,21 @@ ssize_t patty_ax25_sock_write(patty_ax25_sock *sock,
patty_ax25_sock_vs_incr(sock); patty_ax25_sock_vs_incr(sock);
break;
case PATTY_AX25_SOCK_DGRAM:
control = control_ui(0);
if (frame_send(sock, PATTY_AX25_FRAME_COMMAND, control, buf, len) < 0) {
goto error_frame_send;
}
break;
case PATTY_AX25_SOCK_RAW:
return patty_ax25_if_send(sock->iface, buf, len);
}
return len; return len;
error_frame_send: error_frame_send: