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_UI = 0x03,
PATTY_AX25_FRAME_XID = 0xaf,
PATTY_AX25_FRAME_TEST = 0xe3,
PATTY_AX25_FRAME_UNKNOWN = 0xff
PATTY_AX25_FRAME_TEST = 0xe3
};
typedef struct _patty_ax25_frame {

View file

@ -39,6 +39,7 @@
enum patty_ax25_sock_type {
PATTY_AX25_SOCK_STREAM,
PATTY_AX25_SOCK_DGRAM,
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->ns = 0;
frame->pf = 0;
frame->type = PATTY_AX25_FRAME_UNKNOWN;
frame->type = 0xff;
frame->proto = PATTY_AX25_PROTO_UNKNOWN;
frame->info = NULL;
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));
sock->state = PATTY_AX25_SOCK_PENDING_CONNECT;
if (sock_save_remote(server, sock) < 0) {
goto error_sock_save_remote;
}
@ -852,21 +850,34 @@ static int server_connect(patty_ax25_server *server,
goto error_client_save_by_sock;
}
/*
* Send an XID frame, to attempt to negotiate AX.25 v2.2 and its default
* parameters.
*/
if (patty_ax25_sock_send_xid(sock, PATTY_AX25_FRAME_COMMAND) < 0) {
return respond_connect(client, -1, errno);
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 parameters.
*/
if (patty_ax25_sock_send_xid(sock, PATTY_AX25_FRAME_COMMAND) < 0) {
return respond_connect(client, -1, errno);
}
/*
* 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, or whether the peer is not accepting connections.
*/
patty_timer_start(&sock->timer_t1, sock->n_ack);
default:
break;
}
patty_timer_start(&sock->timer_t1, sock->n_ack);
/*
* 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,
* or whether the peer is not accepting connections.
*/
return 0;
error_client_save_by_sock:
@ -1396,6 +1407,17 @@ error_write:
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,
patty_ax25_if *iface,
patty_ax25_sock *sock,
@ -1690,6 +1712,7 @@ static int handle_frame(patty_ax25_server *server,
switch (frame.type) {
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_RNR: return handle_rnr(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_DISC: return handle_disc(server, iface, sock, &frame);
case PATTY_AX25_FRAME_FRMR: return handle_frmr(server, iface, sock, &frame);
default:
break;
}
return 0;

View file

@ -111,26 +111,28 @@ error_realloc_tx_buf:
return -1;
}
static patty_ax25_sock *init_raw(patty_ax25_sock *sock) {
if (bind_pty(sock) < 0) {
goto error_bind_pty;
}
static patty_ax25_sock *init_dgram(patty_ax25_sock *sock,
enum patty_ax25_proto proto) {
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) {
goto error_kiss_tnc_new_fd;
}
sock->proto = PATTY_AX25_PROTO_NONE;
sock->type = PATTY_AX25_SOCK_RAW;
sock->state = PATTY_AX25_SOCK_ESTABLISHED;
return sock;
error_kiss_tnc_new_fd:
(void)close(sock->fd);
error_bind_pty:
free(sock);
return NULL;
}
@ -144,11 +146,20 @@ patty_ax25_sock *patty_ax25_sock_new(enum patty_ax25_proto proto,
memset(sock, '\0', sizeof(*sock));
if (type == PATTY_AX25_SOCK_RAW) {
return init_raw(sock);
if (bind_pty(sock) < 0) {
goto error_bind_pty;
}
patty_ax25_sock_init(sock);
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);
}
sock->proto = proto;
sock->type = type;
@ -160,18 +171,14 @@ patty_ax25_sock *patty_ax25_sock_new(enum patty_ax25_proto proto,
goto error_init_bufs;
}
if (bind_pty(sock) < 0) {
goto error_bind_pty;
}
return sock;
error_bind_pty:
error_init_bufs:
if (sock->tx_slots) free(sock->tx_slots);
if (sock->rx_buf) free(sock->rx_buf);
if (sock->tx_buf) free(sock->tx_buf);
error_bind_pty:
free(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,
enum patty_ax25_frame_type type,
int flag) {
@ -719,24 +730,37 @@ ssize_t patty_ax25_sock_write(patty_ax25_sock *sock,
size_t len) {
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) {
errno = EBADF;
goto error_invalid_mode;
}
control = control_i(sock, 0);
switch (sock->type) {
case PATTY_AX25_SOCK_STREAM:
control = control_i(sock, 0);
if (frame_send(sock, PATTY_AX25_FRAME_COMMAND, control, buf, len) < 0) {
goto error_frame_send;
if (frame_send(sock, PATTY_AX25_FRAME_COMMAND, control, buf, len) < 0) {
goto error_frame_send;
}
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);
}
patty_ax25_sock_vs_incr(sock);
return len;
error_frame_send: