Refactor to adhere better to AX.25 v2.2
Changes: * Don't use a separate dict for keeping track of sockets pending accept and sockets pending connect; rely more on the semantic meaning of the enum patty_ax25_sock_status values * Ensure DISC frames are acknowledged by UA frames * Ensure a receiving system only shuts down a connection after receiving a UA frame in response to a sent DISC frame * Ensure a sending system only shuts down a connection just prior to sending a UA frame in response to a received DISC frame * Don't use the P/F flag for the connection management U frames; implicitly assume the P/F flag is set to 1, and always send frames with a true P/F flag
This commit is contained in:
parent
edfc32ce33
commit
8761a4e3c2
2 changed files with 319 additions and 234 deletions
|
@ -30,7 +30,8 @@ enum patty_ax25_sock_status {
|
||||||
PATTY_AX25_SOCK_LISTENING,
|
PATTY_AX25_SOCK_LISTENING,
|
||||||
PATTY_AX25_SOCK_PENDING_ACCEPT,
|
PATTY_AX25_SOCK_PENDING_ACCEPT,
|
||||||
PATTY_AX25_SOCK_PENDING_CONNECT,
|
PATTY_AX25_SOCK_PENDING_CONNECT,
|
||||||
PATTY_AX25_SOCK_ESTABLISHED
|
PATTY_AX25_SOCK_ESTABLISHED,
|
||||||
|
PATTY_AX25_SOCK_PROMISC
|
||||||
};
|
};
|
||||||
|
|
||||||
enum patty_ax25_sock_mode {
|
enum patty_ax25_sock_mode {
|
||||||
|
|
552
src/server.c
552
src/server.c
|
@ -29,9 +29,9 @@ struct _patty_ax25_server {
|
||||||
patty_ax25_route_table *routes;
|
patty_ax25_route_table *routes;
|
||||||
|
|
||||||
patty_dict *socks_by_fd,
|
patty_dict *socks_by_fd,
|
||||||
*socks_pending_accept,
|
*socks_by_client,
|
||||||
*socks_pending_connect,
|
*socks_local,
|
||||||
*socks_established;
|
*socks_remote;
|
||||||
|
|
||||||
patty_dict *clients,
|
patty_dict *clients,
|
||||||
*clients_by_sock;
|
*clients_by_sock;
|
||||||
|
@ -60,16 +60,16 @@ patty_ax25_server *patty_ax25_server_new(const char *path) {
|
||||||
goto error_dict_new_socks_by_fd;
|
goto error_dict_new_socks_by_fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((server->socks_pending_accept = patty_dict_new()) == NULL) {
|
if ((server->socks_by_client = patty_dict_new()) == NULL) {
|
||||||
goto error_dict_new_socks_pending_accept;
|
goto error_dict_new_socks_by_client;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((server->socks_pending_connect = patty_dict_new()) == NULL) {
|
if ((server->socks_local = patty_dict_new()) == NULL) {
|
||||||
goto error_dict_new_socks_pending_connect;
|
goto error_dict_new_socks_local;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((server->socks_established = patty_dict_new()) == NULL) {
|
if ((server->socks_remote = patty_dict_new()) == NULL) {
|
||||||
goto error_dict_new_socks_established;
|
goto error_dict_new_socks_remote;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((server->clients = patty_dict_new()) == NULL) {
|
if ((server->clients = patty_dict_new()) == NULL) {
|
||||||
|
@ -86,15 +86,15 @@ error_dict_new_clients_by_sock:
|
||||||
patty_dict_destroy(server->clients);
|
patty_dict_destroy(server->clients);
|
||||||
|
|
||||||
error_dict_new_clients:
|
error_dict_new_clients:
|
||||||
patty_dict_destroy(server->socks_established);
|
patty_dict_destroy(server->socks_remote);
|
||||||
|
|
||||||
error_dict_new_socks_established:
|
error_dict_new_socks_remote:
|
||||||
patty_dict_destroy(server->socks_pending_connect);
|
patty_dict_destroy(server->socks_local);
|
||||||
|
|
||||||
error_dict_new_socks_pending_connect:
|
error_dict_new_socks_local:
|
||||||
patty_dict_destroy(server->socks_pending_accept);
|
patty_dict_destroy(server->socks_by_client);
|
||||||
|
|
||||||
error_dict_new_socks_pending_accept:
|
error_dict_new_socks_by_client:
|
||||||
patty_dict_destroy(server->socks_by_fd);
|
patty_dict_destroy(server->socks_by_fd);
|
||||||
|
|
||||||
error_dict_new_socks_by_fd:
|
error_dict_new_socks_by_fd:
|
||||||
|
@ -116,12 +116,19 @@ static int destroy_if(patty_ax25_if *iface, void *ctx) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int destroy_socks_by_client_entry(uint32_t key, void *value, void *ctx) {
|
||||||
|
patty_dict_destroy((patty_dict *)value);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void patty_ax25_server_destroy(patty_ax25_server *server) {
|
void patty_ax25_server_destroy(patty_ax25_server *server) {
|
||||||
patty_dict_destroy(server->clients_by_sock);
|
patty_dict_destroy(server->clients_by_sock);
|
||||||
patty_dict_destroy(server->clients);
|
patty_dict_destroy(server->clients);
|
||||||
patty_dict_destroy(server->socks_established);
|
patty_dict_destroy(server->socks_remote);
|
||||||
patty_dict_destroy(server->socks_pending_connect);
|
patty_dict_destroy(server->socks_local);
|
||||||
patty_dict_destroy(server->socks_pending_accept);
|
patty_dict_each(server->socks_by_client, destroy_socks_by_client_entry, NULL);
|
||||||
|
patty_dict_destroy(server->socks_by_client);
|
||||||
patty_dict_destroy(server->socks_by_fd);
|
patty_dict_destroy(server->socks_by_fd);
|
||||||
|
|
||||||
patty_ax25_server_each_if(server, destroy_if, NULL);
|
patty_ax25_server_each_if(server, destroy_if, NULL);
|
||||||
|
@ -185,9 +192,7 @@ static patty_ax25_sock *sock_by_addrpair(patty_dict *dict,
|
||||||
}
|
}
|
||||||
|
|
||||||
static int sock_save_by_fd(patty_dict *dict, patty_ax25_sock *sock) {
|
static int sock_save_by_fd(patty_dict *dict, patty_ax25_sock *sock) {
|
||||||
if (patty_dict_set(dict,
|
if (patty_dict_set(dict, (uint32_t)sock->fd, sock) == NULL) {
|
||||||
(uint32_t)sock->fd,
|
|
||||||
sock) == NULL) {
|
|
||||||
goto error_dict_set;
|
goto error_dict_set;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -229,7 +234,8 @@ error_dict_set:
|
||||||
|
|
||||||
static inline int client_delete_by_sock(patty_ax25_server *server,
|
static inline int client_delete_by_sock(patty_ax25_server *server,
|
||||||
patty_ax25_sock *sock) {
|
patty_ax25_sock *sock) {
|
||||||
return patty_dict_delete(server->clients_by_sock, (uint32_t)sock->fd);
|
return patty_dict_delete(server->clients_by_sock,
|
||||||
|
(uint32_t)sock->fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline uint32_t hash_addr(patty_ax25_addr *addr) {
|
static inline uint32_t hash_addr(patty_ax25_addr *addr) {
|
||||||
|
@ -254,87 +260,132 @@ static inline uint32_t hash_addrpair(patty_ax25_addr *local,
|
||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int sock_save_by_addr(patty_dict *dict,
|
static int sock_save_local(patty_ax25_server *server,
|
||||||
patty_ax25_sock *sock,
|
patty_ax25_sock *sock) {
|
||||||
patty_ax25_addr *addr) {
|
uint32_t hash = hash_addr(&sock->local);
|
||||||
uint32_t hash = hash_addr(addr);
|
|
||||||
|
|
||||||
if (patty_dict_set(dict,
|
return patty_dict_set(server->socks_local, hash, sock) == NULL? -1: 0;
|
||||||
hash,
|
|
||||||
sock) == NULL) {
|
|
||||||
goto error_dict_set;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
static int sock_save_remote(patty_ax25_server *server,
|
||||||
|
patty_ax25_sock *sock) {
|
||||||
|
uint32_t hash = hash_addrpair(&sock->local, &sock->remote);
|
||||||
|
|
||||||
error_dict_set:
|
return patty_dict_set(server->socks_remote, hash, sock) == NULL? -1: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int sock_delete_local(patty_ax25_server *server,
|
||||||
|
patty_ax25_sock *sock) {
|
||||||
|
uint32_t hash = hash_addr(&sock->local);
|
||||||
|
|
||||||
|
return patty_dict_delete(server->socks_local, hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int sock_delete_remote(patty_ax25_server *server,
|
||||||
|
patty_ax25_sock *sock) {
|
||||||
|
uint32_t hash = hash_addrpair(&sock->local, &sock->remote);
|
||||||
|
|
||||||
|
return patty_dict_delete(server->socks_remote, hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int sock_shutdown(patty_ax25_server *server,
|
||||||
|
patty_ax25_sock *sock) {
|
||||||
|
fd_clear(server, sock->fd);
|
||||||
|
|
||||||
|
return sock->status == PATTY_AX25_SOCK_ESTABLISHED?
|
||||||
|
patty_ax25_sock_send_disc(sock, PATTY_AX25_FRAME_POLL): 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int sock_save(patty_ax25_server *server,
|
||||||
|
int client,
|
||||||
|
patty_ax25_sock *sock) {
|
||||||
|
patty_dict *socks;
|
||||||
|
|
||||||
|
switch (sock->status) {
|
||||||
|
case PATTY_AX25_SOCK_LISTENING:
|
||||||
|
if (sock_save_local(server, sock) < 0) {
|
||||||
|
goto error_sock_save_local;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PATTY_AX25_SOCK_PENDING_ACCEPT:
|
||||||
|
case PATTY_AX25_SOCK_PENDING_CONNECT:
|
||||||
|
case PATTY_AX25_SOCK_ESTABLISHED:
|
||||||
|
if (sock_save_remote(server, sock) < 0) {
|
||||||
|
goto error_sock_save_remote;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PATTY_AX25_SOCK_CLOSED:
|
||||||
|
case PATTY_AX25_SOCK_PROMISC:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (client_save_by_sock(server, client, sock) < 0) {
|
||||||
|
goto error_client_save_by_sock;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((socks = patty_dict_get(server->socks_by_client, client)) == NULL) {
|
||||||
|
goto error_dict_get_socks_by_client;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sock_save_by_fd(socks, sock) < 0) {
|
||||||
|
goto error_sock_save_by_fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
return sock_save_by_fd(server->socks_by_fd, sock);
|
||||||
|
|
||||||
|
error_sock_save_by_fd:
|
||||||
|
error_dict_get_socks_by_client:
|
||||||
|
error_client_save_by_sock:
|
||||||
|
error_sock_save_remote:
|
||||||
|
error_sock_save_local:
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int sock_save_by_addrpair(patty_dict *dict,
|
|
||||||
patty_ax25_sock *sock,
|
|
||||||
patty_ax25_addr *local,
|
|
||||||
patty_ax25_addr *remote) {
|
|
||||||
uint32_t hash = hash_addrpair(local, remote);
|
|
||||||
|
|
||||||
if (patty_dict_set(dict,
|
|
||||||
hash,
|
|
||||||
sock) == NULL) {
|
|
||||||
goto error_dict_set;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
error_dict_set:
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int sock_delete_by_addr(patty_dict *dict,
|
|
||||||
patty_ax25_addr *addr) {
|
|
||||||
uint32_t hash = hash_addr(addr);
|
|
||||||
|
|
||||||
return patty_dict_delete(dict, hash);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int sock_delete_by_addrpair(patty_dict *dict,
|
|
||||||
patty_ax25_addr *local,
|
|
||||||
patty_ax25_addr *remote) {
|
|
||||||
uint32_t hash = hash_addrpair(local, remote);
|
|
||||||
|
|
||||||
return patty_dict_delete(dict, hash);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int sock_close(patty_ax25_server *server,
|
static int sock_close(patty_ax25_server *server,
|
||||||
patty_ax25_sock *sock) {
|
patty_ax25_sock *sock) {
|
||||||
if (sock->status == PATTY_AX25_SOCK_ESTABLISHED) {
|
int client;
|
||||||
if (patty_ax25_sock_send_disc(sock, PATTY_AX25_FRAME_POLL) < 0) {
|
patty_dict *socks;
|
||||||
goto error_sock_send_disc;
|
|
||||||
|
switch (sock->status) {
|
||||||
|
case PATTY_AX25_SOCK_LISTENING:
|
||||||
|
if (sock_delete_local(server, sock) < 0) {
|
||||||
|
goto error_sock_delete_local;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sock_delete_by_addrpair(server->socks_established,
|
break;
|
||||||
&sock->local,
|
|
||||||
&sock->remote) < 0) {
|
case PATTY_AX25_SOCK_PENDING_ACCEPT:
|
||||||
goto error_sock_delete_by_addrpair_established;
|
case PATTY_AX25_SOCK_PENDING_CONNECT:
|
||||||
}
|
case PATTY_AX25_SOCK_ESTABLISHED:
|
||||||
|
if (sock_delete_remote(server, sock) < 0) {
|
||||||
|
goto error_sock_delete_remote;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sock->status == PATTY_AX25_SOCK_PENDING_CONNECT) {
|
break;
|
||||||
if (sock_delete_by_addrpair(server->socks_pending_connect,
|
|
||||||
&sock->local,
|
case PATTY_AX25_SOCK_CLOSED:
|
||||||
&sock->remote) < 0) {
|
case PATTY_AX25_SOCK_PROMISC:
|
||||||
goto error_sock_delete_by_addrpair_pending_connect;
|
break;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sock->status == PATTY_AX25_SOCK_PENDING_ACCEPT) {
|
if ((client = client_by_sock(server, sock)) < 0) {
|
||||||
if (sock_delete_by_addr(server->socks_pending_accept,
|
goto error_client_by_sock;
|
||||||
&sock->local) < 0) {
|
|
||||||
goto error_sock_delete_by_addr_pending_accept;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((socks = patty_dict_get(server->socks_by_client, client)) == NULL) {
|
||||||
|
goto error_dict_get_socks_by_client;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (patty_dict_delete(socks, (uint32_t)sock->fd) < 0) {
|
||||||
|
goto error_dict_delete_by_fd_socks;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (patty_dict_delete(server->socks_by_fd, (uint32_t)sock->fd) < 0) {
|
if (patty_dict_delete(server->socks_by_fd, (uint32_t)sock->fd) < 0) {
|
||||||
goto error_dict_delete_by_fd_socks;
|
goto error_dict_delete_by_fd_socks_by_fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
(void)client_delete_by_sock(server, sock);
|
(void)client_delete_by_sock(server, sock);
|
||||||
|
@ -345,11 +396,12 @@ static int sock_close(patty_ax25_server *server,
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
error_dict_delete_by_fd_socks_by_fd:
|
||||||
error_dict_delete_by_fd_socks:
|
error_dict_delete_by_fd_socks:
|
||||||
error_sock_delete_by_addr_pending_accept:
|
error_dict_get_socks_by_client:
|
||||||
error_sock_delete_by_addrpair_pending_connect:
|
error_client_by_sock:
|
||||||
error_sock_delete_by_addrpair_established:
|
error_sock_delete_remote:
|
||||||
error_sock_send_disc:
|
error_sock_delete_local:
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -391,16 +443,11 @@ int patty_ax25_server_delete_if(patty_ax25_server *server,
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((fd = patty_kiss_tnc_fd(iface->tnc)) >= 0) {
|
if ((fd = patty_kiss_tnc_fd(iface->tnc)) >= 0) {
|
||||||
fd_watch(server, fd);
|
fd_clear(server, fd);
|
||||||
|
|
||||||
if (patty_dict_delete(server->socks_by_fd, (uint32_t)fd) < 0) {
|
|
||||||
goto error_dict_delete;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
error_dict_delete:
|
|
||||||
error_list_splice:
|
error_list_splice:
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -463,15 +510,8 @@ static int server_socket(patty_ax25_server *server,
|
||||||
goto error_sock_new;
|
goto error_sock_new;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sock_save_by_fd(server->socks_by_fd, sock) < 0) {
|
if (sock_save(server, client, sock) < 0) {
|
||||||
response.ret = -1;
|
goto error_sock_save;
|
||||||
response.eno = errno;
|
|
||||||
|
|
||||||
goto error_sock_save_by_fd;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (client_save_by_sock(server, client, sock) < 0) {
|
|
||||||
goto error_client_save_by_sock;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
response.ret = sock->fd;
|
response.ret = sock->fd;
|
||||||
|
@ -481,8 +521,7 @@ static int server_socket(patty_ax25_server *server,
|
||||||
|
|
||||||
return write(client, &response, sizeof(response));
|
return write(client, &response, sizeof(response));
|
||||||
|
|
||||||
error_client_save_by_sock:
|
error_sock_save:
|
||||||
error_sock_save_by_fd:
|
|
||||||
patty_ax25_sock_destroy(sock);
|
patty_ax25_sock_destroy(sock);
|
||||||
|
|
||||||
error_sock_new:
|
error_sock_new:
|
||||||
|
@ -533,9 +572,7 @@ static int server_setsockopt(patty_ax25_server *server,
|
||||||
|
|
||||||
patty_ax25_sock_bind_if(sock, iface);
|
patty_ax25_sock_bind_if(sock, iface);
|
||||||
|
|
||||||
if (sock_save_by_fd(server->socks_established, sock) < 0) {
|
sock->status = PATTY_AX25_SOCK_PROMISC;
|
||||||
goto error_sock_save_by_fd;
|
|
||||||
}
|
|
||||||
|
|
||||||
fd_watch(server, sock->fd);
|
fd_watch(server, sock->fd);
|
||||||
|
|
||||||
|
@ -558,7 +595,6 @@ error_invalid_type:
|
||||||
error_invalid_opt:
|
error_invalid_opt:
|
||||||
return write(client, &response, sizeof(response));
|
return write(client, &response, sizeof(response));
|
||||||
|
|
||||||
error_sock_save_by_fd:
|
|
||||||
error_read:
|
error_read:
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -632,6 +668,10 @@ static int server_listen(patty_ax25_server *server,
|
||||||
|
|
||||||
sock->status = PATTY_AX25_SOCK_LISTENING;
|
sock->status = PATTY_AX25_SOCK_LISTENING;
|
||||||
|
|
||||||
|
if (sock_save_local(server, sock) < 0) {
|
||||||
|
goto error_sock_save_local;
|
||||||
|
}
|
||||||
|
|
||||||
response.ret = 0;
|
response.ret = 0;
|
||||||
response.eno = 0;
|
response.eno = 0;
|
||||||
|
|
||||||
|
@ -639,6 +679,7 @@ error_invalid_fd:
|
||||||
error_sock_by_fd:
|
error_sock_by_fd:
|
||||||
return write(client, &response, sizeof(response));
|
return write(client, &response, sizeof(response));
|
||||||
|
|
||||||
|
error_sock_save_local:
|
||||||
error_io:
|
error_io:
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -661,18 +702,11 @@ static int server_accept(patty_ax25_server *server,
|
||||||
goto error_sock_by_fd;
|
goto error_sock_by_fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sock_save_by_addr(server->socks_pending_accept,
|
|
||||||
sock,
|
|
||||||
&sock->local) < 0) {
|
|
||||||
goto error_save_by_addr;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
error_sock_by_fd:
|
error_sock_by_fd:
|
||||||
return write(client, &response, sizeof(response));
|
return write(client, &response, sizeof(response));
|
||||||
|
|
||||||
error_save_by_addr:
|
|
||||||
error_io:
|
error_io:
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -759,11 +793,8 @@ static int server_connect(patty_ax25_server *server,
|
||||||
|
|
||||||
sock->status = PATTY_AX25_SOCK_PENDING_CONNECT;
|
sock->status = PATTY_AX25_SOCK_PENDING_CONNECT;
|
||||||
|
|
||||||
if (sock_save_by_addrpair(server->socks_pending_connect,
|
if (sock_save_remote(server, sock) < 0) {
|
||||||
sock,
|
goto error_sock_save_remote;
|
||||||
&sock->local,
|
|
||||||
&sock->remote) < 0) {
|
|
||||||
goto error_sock_save_by_addrpair;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (client_save_by_sock(server, client, sock) < 0) {
|
if (client_save_by_sock(server, client, sock) < 0) {
|
||||||
|
@ -795,7 +826,7 @@ error_sock_by_fd:
|
||||||
return write(client, &response, sizeof(response));
|
return write(client, &response, sizeof(response));
|
||||||
|
|
||||||
error_client_save_by_sock:
|
error_client_save_by_sock:
|
||||||
error_sock_save_by_addrpair:
|
error_sock_save_remote:
|
||||||
error_io:
|
error_io:
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -806,6 +837,7 @@ static int server_close(patty_ax25_server *server,
|
||||||
patty_ax25_call_close_response response;
|
patty_ax25_call_close_response response;
|
||||||
|
|
||||||
patty_ax25_sock *sock;
|
patty_ax25_sock *sock;
|
||||||
|
patty_dict *socks;
|
||||||
|
|
||||||
if (read(client, &request, sizeof(request)) < 0) {
|
if (read(client, &request, sizeof(request)) < 0) {
|
||||||
goto error_io;
|
goto error_io;
|
||||||
|
@ -818,17 +850,33 @@ static int server_close(patty_ax25_server *server,
|
||||||
goto error_sock_by_fd;
|
goto error_sock_by_fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((socks = patty_dict_get(server->socks_by_client, client)) == NULL) {
|
||||||
|
response.ret = -1;
|
||||||
|
response.eno = EBADF;
|
||||||
|
|
||||||
|
goto error_dict_get_socks_by_client;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sock_shutdown(server, sock) < 0) {
|
||||||
|
response.ret = -1;
|
||||||
|
response.eno = errno;
|
||||||
|
|
||||||
|
goto error_sock_shutdown;
|
||||||
|
}
|
||||||
|
|
||||||
if (sock_close(server, sock) < 0) {
|
if (sock_close(server, sock) < 0) {
|
||||||
response.ret = -1;
|
response.ret = -1;
|
||||||
response.eno = EBADF;
|
response.eno = EBADF;
|
||||||
|
|
||||||
goto error_sock_delete;
|
goto error_sock_close;
|
||||||
}
|
}
|
||||||
|
|
||||||
response.ret = 0;
|
response.ret = 0;
|
||||||
response.eno = 0;
|
response.eno = 0;
|
||||||
|
|
||||||
error_sock_delete:
|
error_sock_close:
|
||||||
|
error_sock_shutdown:
|
||||||
|
error_dict_get_socks_by_client:
|
||||||
error_sock_by_fd:
|
error_sock_by_fd:
|
||||||
return write(client, &response, sizeof(response));
|
return write(client, &response, sizeof(response));
|
||||||
|
|
||||||
|
@ -896,6 +944,7 @@ static int accept_client(patty_ax25_server *server) {
|
||||||
int fd;
|
int fd;
|
||||||
struct sockaddr addr;
|
struct sockaddr addr;
|
||||||
socklen_t addrlen = sizeof(addr);
|
socklen_t addrlen = sizeof(addr);
|
||||||
|
patty_dict *socks;
|
||||||
|
|
||||||
memset(&addr, '\0', addrlen);
|
memset(&addr, '\0', addrlen);
|
||||||
|
|
||||||
|
@ -907,8 +956,16 @@ static int accept_client(patty_ax25_server *server) {
|
||||||
goto error_accept;
|
goto error_accept;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((socks = patty_dict_new()) == NULL) {
|
||||||
|
goto error_dict_new;
|
||||||
|
}
|
||||||
|
|
||||||
if (patty_dict_set(server->clients, (uint32_t)fd, NULL + fd) == NULL) {
|
if (patty_dict_set(server->clients, (uint32_t)fd, NULL + fd) == NULL) {
|
||||||
goto error_dict_set;
|
goto error_dict_set_clients;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (patty_dict_set(server->socks_by_client, (uint32_t)fd, socks) == NULL) {
|
||||||
|
goto error_dict_set_socks_by_client;
|
||||||
}
|
}
|
||||||
|
|
||||||
fd_watch(server, fd);
|
fd_watch(server, fd);
|
||||||
|
@ -916,13 +973,31 @@ static int accept_client(patty_ax25_server *server) {
|
||||||
done:
|
done:
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
error_dict_set:
|
error_dict_set_socks_by_client:
|
||||||
|
error_dict_set_clients:
|
||||||
|
patty_dict_destroy(socks);
|
||||||
|
|
||||||
|
error_dict_new:
|
||||||
close(fd);
|
close(fd);
|
||||||
|
|
||||||
error_accept:
|
error_accept:
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int client_sock_close(uint32_t key, void *value, void *ctx) {
|
||||||
|
patty_ax25_server *server = ctx;
|
||||||
|
patty_ax25_sock *sock = value;
|
||||||
|
|
||||||
|
if (sock_shutdown(server, sock) < 0) {
|
||||||
|
goto error_sock_shutdown;
|
||||||
|
}
|
||||||
|
|
||||||
|
return sock_close(server, sock);
|
||||||
|
|
||||||
|
error_sock_shutdown:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
static int handle_client(uint32_t key,
|
static int handle_client(uint32_t key,
|
||||||
void *value,
|
void *value,
|
||||||
void *ctx) {
|
void *ctx) {
|
||||||
|
@ -939,10 +1014,21 @@ static int handle_client(uint32_t key,
|
||||||
if ((readlen = read(client, &call, sizeof(call))) < 0) {
|
if ((readlen = read(client, &call, sizeof(call))) < 0) {
|
||||||
goto error_io;
|
goto error_io;
|
||||||
} else if (readlen == 0) {
|
} else if (readlen == 0) {
|
||||||
|
patty_dict *socks;
|
||||||
|
|
||||||
fd_clear(server, client);
|
fd_clear(server, client);
|
||||||
|
|
||||||
|
if ((socks = patty_dict_get(server->socks_by_client, client)) != NULL) {
|
||||||
|
(void)patty_dict_each(socks, client_sock_close, server);
|
||||||
|
(void)patty_dict_destroy(socks);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (patty_dict_delete(server->socks_by_client, key) < 0) {
|
||||||
|
goto error_dict_delete_socks_by_client;
|
||||||
|
}
|
||||||
|
|
||||||
if (patty_dict_delete(server->clients, key) < 0) {
|
if (patty_dict_delete(server->clients, key) < 0) {
|
||||||
goto error_dict_delete;
|
goto error_dict_delete_clients;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (close(client) < 0) {
|
if (close(client) < 0) {
|
||||||
|
@ -968,7 +1054,8 @@ done:
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
error_not_implemented:
|
error_not_implemented:
|
||||||
error_dict_delete:
|
error_dict_delete_socks_by_client:
|
||||||
|
error_dict_delete_clients:
|
||||||
error_io:
|
error_io:
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -1000,6 +1087,8 @@ static int reply_to(patty_ax25_if *iface,
|
||||||
patty_ax25_frame *reply) {
|
patty_ax25_frame *reply) {
|
||||||
ssize_t len;
|
ssize_t len;
|
||||||
|
|
||||||
|
frame->cr = PATTY_AX25_FRAME_RESPONSE;
|
||||||
|
|
||||||
if ((len = patty_ax25_frame_encode_reply_to(frame,
|
if ((len = patty_ax25_frame_encode_reply_to(frame,
|
||||||
reply,
|
reply,
|
||||||
iface->tx_buf,
|
iface->tx_buf,
|
||||||
|
@ -1036,11 +1125,6 @@ static int reply_ua(patty_ax25_if *iface,
|
||||||
.infolen = 0
|
.infolen = 0
|
||||||
};
|
};
|
||||||
|
|
||||||
char callsign[7];
|
|
||||||
uint8_t ssid;
|
|
||||||
|
|
||||||
patty_ax25_ntop(&frame->dest, callsign, &ssid, sizeof(callsign));
|
|
||||||
|
|
||||||
return reply_to(iface, frame, &reply);
|
return reply_to(iface, frame, &reply);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1049,23 +1133,26 @@ static int handle_frmr(patty_ax25_server *server,
|
||||||
patty_ax25_frame *frame) {
|
patty_ax25_frame *frame) {
|
||||||
patty_ax25_sock *sock;
|
patty_ax25_sock *sock;
|
||||||
|
|
||||||
if ((sock = sock_by_addrpair(server->socks_pending_connect,
|
if ((sock = sock_by_addrpair(server->socks_remote,
|
||||||
&frame->dest,
|
&frame->dest,
|
||||||
&frame->src)) == NULL) {
|
&frame->src)) == NULL) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return patty_ax25_sock_send_sabm(sock, PATTY_AX25_FRAME_POLL);
|
return sock->status == PATTY_AX25_SOCK_PENDING_CONNECT?
|
||||||
|
patty_ax25_sock_send_sabm(sock, PATTY_AX25_FRAME_POLL): 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int handle_sabm(patty_ax25_server *server,
|
static int handle_sabm(patty_ax25_server *server,
|
||||||
patty_ax25_if *iface,
|
patty_ax25_if *iface,
|
||||||
patty_ax25_frame *frame) {
|
patty_ax25_frame *frame) {
|
||||||
int client;
|
int client,
|
||||||
|
created = 0;
|
||||||
|
|
||||||
patty_ax25_sock *local, *remote;
|
patty_ax25_sock *local, *remote;
|
||||||
patty_ax25_call_accept_response response;
|
patty_ax25_call_accept_response response;
|
||||||
|
|
||||||
if ((local = sock_by_addr(server->socks_pending_accept,
|
if ((local = sock_by_addr(server->socks_local,
|
||||||
&frame->dest)) == NULL) {
|
&frame->dest)) == NULL) {
|
||||||
return reply_dm(iface, frame, PATTY_AX25_FRAME_FINAL);
|
return reply_dm(iface, frame, PATTY_AX25_FRAME_FINAL);
|
||||||
}
|
}
|
||||||
|
@ -1074,45 +1161,41 @@ static int handle_sabm(patty_ax25_server *server,
|
||||||
goto error_client_by_sock;
|
goto error_client_by_sock;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Look to see if there is already a remote socket created based on an XID
|
||||||
|
* packet previously received.
|
||||||
|
*/
|
||||||
|
if ((remote = sock_by_addrpair(server->socks_remote,
|
||||||
|
&frame->dest,
|
||||||
|
&frame->src)) == NULL) {
|
||||||
|
/*
|
||||||
|
* If there is no existing remote socket, we should create one, and
|
||||||
|
* associate it with the client.
|
||||||
|
*/
|
||||||
if ((remote = patty_ax25_sock_new(local->proto, local->type)) == NULL) {
|
if ((remote = patty_ax25_sock_new(local->proto, local->type)) == NULL) {
|
||||||
goto error_sock_new;
|
goto error_sock_new;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
save_reply_addr(remote, frame);
|
||||||
|
|
||||||
|
created = 1;
|
||||||
|
}
|
||||||
|
|
||||||
remote->status = PATTY_AX25_SOCK_ESTABLISHED;
|
remote->status = PATTY_AX25_SOCK_ESTABLISHED;
|
||||||
remote->mode = (frame->type == PATTY_AX25_FRAME_SABM)?
|
remote->mode = (frame->type == PATTY_AX25_FRAME_SABME)?
|
||||||
PATTY_AX25_SOCK_SABM: PATTY_AX25_SOCK_SABME;
|
PATTY_AX25_SOCK_SABME: PATTY_AX25_SOCK_SABM;
|
||||||
|
|
||||||
patty_ax25_sock_bind_if(remote, iface);
|
patty_ax25_sock_bind_if(remote, iface);
|
||||||
|
|
||||||
save_reply_addr(remote, frame);
|
if (created) {
|
||||||
|
if (sock_save(server, client, remote) < 0) {
|
||||||
if (sock_save_by_fd(server->socks_by_fd, remote) < 0) {
|
goto error_sock_save;
|
||||||
goto error_sock_save_by_fd;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sock_save_by_addrpair(server->socks_established,
|
fd_watch(server, remote->fd);
|
||||||
remote,
|
|
||||||
&remote->local,
|
|
||||||
&remote->remote) < 0) {
|
|
||||||
goto error_sock_save_by_addrpair;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sock_delete_by_addr(server->socks_pending_accept,
|
|
||||||
&local->local) < 0) {
|
|
||||||
goto error_sock_delete_by_addr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (frame->pf) {
|
|
||||||
if (reply_ua(iface, frame, PATTY_AX25_FRAME_FINAL) < 0) {
|
|
||||||
goto error_reply_ua;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(&response, '\0', sizeof(response));
|
memset(&response, '\0', sizeof(response));
|
||||||
|
|
||||||
response.ret = 0;
|
|
||||||
response.eno = 0;
|
|
||||||
|
|
||||||
memcpy(&response.peer, &frame->src, sizeof(patty_ax25_addr));
|
memcpy(&response.peer, &frame->src, sizeof(patty_ax25_addr));
|
||||||
memcpy(&response.path, &remote->path, sizeof(response.path));
|
memcpy(&response.path, &remote->path, sizeof(response.path));
|
||||||
|
|
||||||
|
@ -1120,15 +1203,10 @@ static int handle_sabm(patty_ax25_server *server,
|
||||||
goto error_write;
|
goto error_write;
|
||||||
}
|
}
|
||||||
|
|
||||||
fd_watch(server, remote->fd);
|
return reply_ua(iface, frame, PATTY_AX25_FRAME_FINAL);
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
error_write:
|
error_write:
|
||||||
error_reply_ua:
|
error_sock_save:
|
||||||
error_sock_delete_by_addr:
|
|
||||||
error_sock_save_by_addrpair:
|
|
||||||
error_sock_save_by_fd:
|
|
||||||
patty_ax25_sock_destroy(remote);
|
patty_ax25_sock_destroy(remote);
|
||||||
|
|
||||||
error_sock_new:
|
error_sock_new:
|
||||||
|
@ -1143,34 +1221,34 @@ static int handle_ua(patty_ax25_server *server,
|
||||||
patty_ax25_sock *sock;
|
patty_ax25_sock *sock;
|
||||||
patty_ax25_call_connect_response response;
|
patty_ax25_call_connect_response response;
|
||||||
|
|
||||||
if ((sock = sock_by_addrpair(server->socks_pending_connect,
|
if ((sock = sock_by_addrpair(server->socks_remote,
|
||||||
&frame->dest,
|
&frame->dest,
|
||||||
&frame->src)) == NULL) {
|
&frame->src)) == NULL) {
|
||||||
return reply_dm(iface, frame, PATTY_AX25_FRAME_FINAL);
|
return reply_dm(iface, frame, PATTY_AX25_FRAME_FINAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((client = client_by_sock(server, sock)) < 0) {
|
switch (sock->status) {
|
||||||
goto error_client_by_sock;
|
case PATTY_AX25_SOCK_PENDING_CONNECT:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PATTY_AX25_SOCK_ESTABLISHED:
|
||||||
|
return sock_close(server, sock);
|
||||||
|
|
||||||
|
default:
|
||||||
|
return reply_dm(iface, frame, PATTY_AX25_FRAME_FINAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
sock->status = PATTY_AX25_SOCK_ESTABLISHED;
|
sock->status = PATTY_AX25_SOCK_ESTABLISHED;
|
||||||
|
|
||||||
if (sock->mode == PATTY_AX25_SOCK_DM) {
|
if ((client = client_by_sock(server, sock)) < 0) {
|
||||||
sock->mode = PATTY_AX25_SOCK_SABM;
|
goto error_client_by_sock;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sock_save_by_addrpair(server->socks_established,
|
if (sock_save(server, client, sock) < 0) {
|
||||||
sock,
|
goto error_sock_save;
|
||||||
&sock->local,
|
|
||||||
&sock->remote) < 0) {
|
|
||||||
goto error_save_by_addrpair;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sock_delete_by_addrpair(server->socks_pending_connect,
|
fd_watch(server, sock->fd);
|
||||||
&sock->local,
|
|
||||||
&sock->remote) < 0) {
|
|
||||||
goto error_delete_by_addrpair;
|
|
||||||
}
|
|
||||||
|
|
||||||
response.ret = 0;
|
response.ret = 0;
|
||||||
response.eno = 0;
|
response.eno = 0;
|
||||||
|
@ -1179,15 +1257,12 @@ static int handle_ua(patty_ax25_server *server,
|
||||||
goto error_write;
|
goto error_write;
|
||||||
}
|
}
|
||||||
|
|
||||||
fd_watch(server, sock->fd);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
error_write:
|
error_write:
|
||||||
|
error_sock_save:
|
||||||
patty_ax25_sock_destroy(sock);
|
patty_ax25_sock_destroy(sock);
|
||||||
|
|
||||||
error_delete_by_addrpair:
|
|
||||||
error_save_by_addrpair:
|
|
||||||
error_client_by_sock:
|
error_client_by_sock:
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -1199,26 +1274,18 @@ static int handle_dm(patty_ax25_server *server,
|
||||||
patty_ax25_sock *sock;
|
patty_ax25_sock *sock;
|
||||||
patty_ax25_call_connect_response response;
|
patty_ax25_call_connect_response response;
|
||||||
|
|
||||||
if ((sock = sock_by_addrpair(server->socks_established,
|
if ((sock = sock_by_addrpair(server->socks_remote,
|
||||||
&frame->dest,
|
|
||||||
&frame->src)) != NULL) {
|
|
||||||
return sock_close(server, sock);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((sock = sock_by_addrpair(server->socks_pending_connect,
|
|
||||||
&frame->dest,
|
&frame->dest,
|
||||||
&frame->src)) == NULL) {
|
&frame->src)) == NULL) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((client = client_by_sock(server, sock)) < 0) {
|
if (sock->status != PATTY_AX25_SOCK_PENDING_CONNECT) {
|
||||||
goto error_client_by_sock;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sock_delete_by_addrpair(server->socks_pending_connect,
|
if ((client = client_by_sock(server, sock)) < 0) {
|
||||||
&frame->dest,
|
goto error_client_by_sock;
|
||||||
&frame->src) < 0) {
|
|
||||||
goto error_delete_by_addrpair;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
response.ret = -1;
|
response.ret = -1;
|
||||||
|
@ -1233,7 +1300,6 @@ static int handle_dm(patty_ax25_server *server,
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
error_write:
|
error_write:
|
||||||
error_delete_by_addrpair:
|
|
||||||
error_client_by_sock:
|
error_client_by_sock:
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -1269,25 +1335,19 @@ static int handle_disc(patty_ax25_server *server,
|
||||||
patty_ax25_frame *frame) {
|
patty_ax25_frame *frame) {
|
||||||
patty_ax25_sock *sock;
|
patty_ax25_sock *sock;
|
||||||
|
|
||||||
if ((sock = sock_by_addrpair(server->socks_established,
|
if ((sock = sock_by_addrpair(server->socks_remote,
|
||||||
&frame->dest,
|
&frame->dest,
|
||||||
&frame->src)) == NULL) {
|
&frame->src)) == NULL) {
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sock_close(server, sock) < 0) {
|
|
||||||
goto error_sock_delete;
|
|
||||||
}
|
|
||||||
|
|
||||||
done:
|
|
||||||
if (frame->pf) {
|
|
||||||
return reply_dm(iface, frame, PATTY_AX25_FRAME_FINAL);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
error_sock_delete:
|
if (sock->status != PATTY_AX25_SOCK_ESTABLISHED) {
|
||||||
return -1;
|
return frame->pf? reply_dm(iface, frame, PATTY_AX25_FRAME_FINAL): 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
(void)sock_close(server, sock);
|
||||||
|
|
||||||
|
return reply_ua(iface, frame, PATTY_AX25_FRAME_FINAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int handle_rej(patty_ax25_server *server,
|
static int handle_rej(patty_ax25_server *server,
|
||||||
|
@ -1339,18 +1399,25 @@ static int handle_xid(patty_ax25_server *server,
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* First, check if this XID packet is for a pending outbound connection.
|
* First, check if this XID packet is a response to an XID used to initiate
|
||||||
|
* an outbound connection.
|
||||||
*/
|
*/
|
||||||
if ((remote = sock_by_addrpair(server->socks_pending_connect,
|
if ((remote = sock_by_addrpair(server->socks_remote,
|
||||||
&frame->dest,
|
&frame->dest,
|
||||||
&frame->src)) != NULL) {
|
&frame->src)) != NULL) {
|
||||||
|
if (remote->status != PATTY_AX25_SOCK_PENDING_CONNECT) {
|
||||||
|
goto reply_dm;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Since we've received an XID packet, we can assume that the remote
|
* Since we've received an XID packet, we can assume that the remote
|
||||||
* station is capable of speaking AX.25 v2.2. Therefore, we should
|
* station is capable of speaking AX.25 v2.2. Therefore, we should
|
||||||
* upgrade the socket defaults accordingly, and negotiate downwards
|
* upgrade the socket defaults accordingly, and negotiate downwards
|
||||||
* as necessary.
|
* as necessary.
|
||||||
*/
|
*/
|
||||||
patty_ax25_sock_upgrade(remote);
|
if (patty_ax25_sock_upgrade(remote) < 0) {
|
||||||
|
goto error_sock_upgrade;
|
||||||
|
}
|
||||||
|
|
||||||
if (patty_ax25_sock_params_set(remote, ¶ms) < 0) {
|
if (patty_ax25_sock_params_set(remote, ¶ms) < 0) {
|
||||||
goto error_sock_params_set;
|
goto error_sock_params_set;
|
||||||
|
@ -1365,15 +1432,27 @@ static int handle_xid(patty_ax25_server *server,
|
||||||
|
|
||||||
return patty_ax25_sock_send_sabme(remote, PATTY_AX25_FRAME_POLL);
|
return patty_ax25_sock_send_sabme(remote, PATTY_AX25_FRAME_POLL);
|
||||||
} else {
|
} else {
|
||||||
|
remote->mode = PATTY_AX25_SOCK_SABM;
|
||||||
|
|
||||||
return patty_ax25_sock_send_sabm(remote, PATTY_AX25_FRAME_POLL);
|
return patty_ax25_sock_send_sabm(remote, PATTY_AX25_FRAME_POLL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Second, check if this XID packet is for a socket pending accept.
|
* Second, check if this XID packet is for a listening socket.
|
||||||
*/
|
*/
|
||||||
if ((local = sock_by_addr(server->socks_pending_accept,
|
if ((local = sock_by_addr(server->socks_local,
|
||||||
&frame->dest)) != NULL) {
|
&frame->dest)) != NULL) {
|
||||||
|
int client;
|
||||||
|
|
||||||
|
if (local->status != PATTY_AX25_SOCK_LISTENING) {
|
||||||
|
goto reply_dm;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((client = client_by_sock(server, local)) < 0) {
|
||||||
|
goto error_client_by_sock;
|
||||||
|
}
|
||||||
|
|
||||||
if ((remote = patty_ax25_sock_new(local->proto, local->type)) == NULL) {
|
if ((remote = patty_ax25_sock_new(local->proto, local->type)) == NULL) {
|
||||||
goto error_sock_new;
|
goto error_sock_new;
|
||||||
}
|
}
|
||||||
|
@ -1394,18 +1473,21 @@ static int handle_xid(patty_ax25_server *server,
|
||||||
|
|
||||||
save_reply_addr(remote, frame);
|
save_reply_addr(remote, frame);
|
||||||
|
|
||||||
if (sock_save_by_fd(server->socks_by_fd, remote) < 0) {
|
if (sock_save(server, client, remote) < 0) {
|
||||||
goto error_sock_save_by_fd;
|
goto error_sock_save;
|
||||||
}
|
}
|
||||||
|
|
||||||
return patty_ax25_sock_send_xid(remote, PATTY_AX25_FRAME_RESPONSE);
|
return patty_ax25_sock_send_xid(remote, PATTY_AX25_FRAME_RESPONSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
reply_dm:
|
||||||
return reply_dm(iface, frame, PATTY_AX25_FRAME_FINAL);
|
return reply_dm(iface, frame, PATTY_AX25_FRAME_FINAL);
|
||||||
|
|
||||||
error_sock_save_by_fd:
|
error_sock_save:
|
||||||
error_sock_new:
|
error_sock_new:
|
||||||
|
error_client_by_sock:
|
||||||
error_sock_params_set:
|
error_sock_params_set:
|
||||||
|
error_sock_upgrade:
|
||||||
error_io:
|
error_io:
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -1428,7 +1510,7 @@ static int handle_frame(patty_ax25_server *server,
|
||||||
offset += decoded;
|
offset += decoded;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((sock = sock_by_addrpair(server->socks_established,
|
if ((sock = sock_by_addrpair(server->socks_remote,
|
||||||
&frame.dest,
|
&frame.dest,
|
||||||
&frame.src)) != NULL) {
|
&frame.src)) != NULL) {
|
||||||
if (sock->mode == PATTY_AX25_SOCK_SABME) {
|
if (sock->mode == PATTY_AX25_SOCK_SABME) {
|
||||||
|
@ -1469,17 +1551,19 @@ error_io:
|
||||||
static int handle_iface(patty_ax25_server *server, patty_ax25_if *iface) {
|
static int handle_iface(patty_ax25_server *server, patty_ax25_if *iface) {
|
||||||
int fd = patty_kiss_tnc_fd(iface->tnc);
|
int fd = patty_kiss_tnc_fd(iface->tnc);
|
||||||
|
|
||||||
void *buf;
|
|
||||||
ssize_t readlen;
|
|
||||||
|
|
||||||
if (!FD_ISSET(fd, &server->fds_r)) {
|
if (!FD_ISSET(fd, &server->fds_r)) {
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
do {
|
do {
|
||||||
|
void *buf;
|
||||||
|
ssize_t readlen;
|
||||||
|
|
||||||
if ((readlen = patty_ax25_if_recv(iface, &buf)) < 0) {
|
if ((readlen = patty_ax25_if_recv(iface, &buf)) < 0) {
|
||||||
goto error_io;
|
goto error_io;
|
||||||
} else if (readlen == 0) {
|
} else if (readlen == 0) {
|
||||||
|
close(fd);
|
||||||
|
|
||||||
fd_clear(server, fd);
|
fd_clear(server, fd);
|
||||||
|
|
||||||
goto done;
|
goto done;
|
||||||
|
@ -1530,14 +1614,14 @@ static int handle_sock(uint32_t key,
|
||||||
|
|
||||||
if ((len = read(sock->fd, sock->rx_buf, sock->n_maxlen_rx)) < 0) {
|
if ((len = read(sock->fd, sock->rx_buf, sock->n_maxlen_rx)) < 0) {
|
||||||
if (errno == EIO) {
|
if (errno == EIO) {
|
||||||
(void)sock_close(server, sock);
|
(void)sock_shutdown(server, sock);
|
||||||
|
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
goto error_io;
|
goto error_io;
|
||||||
} else if (len == 0) {
|
} else if (len == 0) {
|
||||||
sock_close(server, sock);
|
(void)sock_shutdown(server, sock);
|
||||||
|
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
@ -1555,7 +1639,7 @@ error_io:
|
||||||
}
|
}
|
||||||
|
|
||||||
static int handle_socks(patty_ax25_server *server) {
|
static int handle_socks(patty_ax25_server *server) {
|
||||||
return patty_dict_each(server->socks_established, handle_sock, server);
|
return patty_dict_each(server->socks_by_fd, handle_sock, server);
|
||||||
}
|
}
|
||||||
|
|
||||||
int patty_ax25_server_run(patty_ax25_server *server) {
|
int patty_ax25_server_run(patty_ax25_server *server) {
|
||||||
|
|
Loading…
Add table
Reference in a new issue