Writing a network stack from scratch is extremely tiring
This commit is contained in:
parent
d25b799e4e
commit
ac55d13057
3 changed files with 168 additions and 71 deletions
|
@ -47,9 +47,9 @@ void *patty_dict_set_with_hash(patty_dict *dict,
|
||||||
|
|
||||||
void *patty_dict_set(patty_dict *dict, void *key, size_t keysz, void *value);
|
void *patty_dict_set(patty_dict *dict, void *key, size_t keysz, void *value);
|
||||||
|
|
||||||
void *patty_dict_delete_with_hash(patty_dict *dict, void *key, size_t keysz);
|
int patty_dict_delete_with_hash(patty_dict *dict, uint32_t hash);
|
||||||
|
|
||||||
void *patty_dict_delete(patty_dict *dict, void *key, size_t keysz);
|
int patty_dict_delete(patty_dict *dict, void *key, size_t keysz);
|
||||||
|
|
||||||
void patty_dict_destroy(patty_dict *dict);
|
void patty_dict_destroy(patty_dict *dict);
|
||||||
|
|
||||||
|
|
18
src/dict.c
18
src/dict.c
|
@ -174,21 +174,23 @@ void *patty_dict_set(patty_dict *dict, void *key, size_t keysz, void *value) {
|
||||||
patty_hash(key, keysz));
|
patty_hash(key, keysz));
|
||||||
}
|
}
|
||||||
|
|
||||||
void *patty_dict_delete(patty_dict *dict, void *key, size_t keysz) {
|
int patty_dict_delete_with_hash(patty_dict *dict, uint32_t hash) {
|
||||||
patty_dict_slot *slot;
|
patty_dict_slot *slot;
|
||||||
void *value;
|
|
||||||
|
|
||||||
uint32_t hash = patty_hash(key, keysz);
|
|
||||||
|
|
||||||
if ((slot = patty_dict_slot_find(dict, hash)) == NULL) {
|
if ((slot = patty_dict_slot_find(dict, hash)) == NULL) {
|
||||||
return NULL;
|
goto error_dict_slot_find;
|
||||||
}
|
}
|
||||||
|
|
||||||
value = slot->value;
|
|
||||||
|
|
||||||
memset(slot, '\0', sizeof(*slot));
|
memset(slot, '\0', sizeof(*slot));
|
||||||
|
|
||||||
return value;
|
return 0;
|
||||||
|
|
||||||
|
error_dict_slot_find:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int patty_dict_delete(patty_dict *dict, void *key, size_t keysz) {
|
||||||
|
return patty_dict_delete_with_hash(dict, patty_hash(key, keysz));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int dict_item_release(void *key, size_t keysz, void *value, void *ctx) {
|
static int dict_item_release(void *key, size_t keysz, void *value, void *ctx) {
|
||||||
|
|
211
src/server.c
211
src/server.c
|
@ -14,7 +14,6 @@ struct _patty_ax25_server {
|
||||||
patty_list *ifaces;
|
patty_list *ifaces;
|
||||||
|
|
||||||
patty_dict *socks_by_fd,
|
patty_dict *socks_by_fd,
|
||||||
*socks_bound,
|
|
||||||
*socks_pending_accept,
|
*socks_pending_accept,
|
||||||
*socks_pending_connect,
|
*socks_pending_connect,
|
||||||
*socks_established;
|
*socks_established;
|
||||||
|
@ -37,10 +36,6 @@ int patty_ax25_server_init(patty_ax25_server *server) {
|
||||||
goto error_dict_new_socks_by_fd;
|
goto error_dict_new_socks_by_fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((server->socks_bound = patty_dict_new()) == NULL) {
|
|
||||||
goto error_dict_new_socks_bound;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((server->socks_pending_accept = patty_dict_new()) == NULL) {
|
if ((server->socks_pending_accept = patty_dict_new()) == NULL) {
|
||||||
goto error_dict_new_socks_pending_accept;
|
goto error_dict_new_socks_pending_accept;
|
||||||
}
|
}
|
||||||
|
@ -62,9 +57,6 @@ error_dict_new_socks_pending_connect:
|
||||||
patty_dict_destroy(server->socks_pending_accept);
|
patty_dict_destroy(server->socks_pending_accept);
|
||||||
|
|
||||||
error_dict_new_socks_pending_accept:
|
error_dict_new_socks_pending_accept:
|
||||||
patty_dict_destroy(server->socks_bound);
|
|
||||||
|
|
||||||
error_dict_new_socks_bound:
|
|
||||||
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:
|
||||||
|
@ -84,7 +76,6 @@ void patty_ax25_server_stop(patty_ax25_server *server) {
|
||||||
patty_dict_destroy(server->socks_established);
|
patty_dict_destroy(server->socks_established);
|
||||||
patty_dict_destroy(server->socks_pending_connect);
|
patty_dict_destroy(server->socks_pending_connect);
|
||||||
patty_dict_destroy(server->socks_pending_accept);
|
patty_dict_destroy(server->socks_pending_accept);
|
||||||
patty_dict_destroy(server->socks_bound);
|
|
||||||
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);
|
||||||
|
@ -127,20 +118,6 @@ static inline void hash_end(uint32_t *hash) {
|
||||||
*hash += (*hash << 15);
|
*hash += (*hash << 15);
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t hash_addrpair(patty_ax25_addr *local,
|
|
||||||
patty_ax25_addr *remote) {
|
|
||||||
uint32_t hash;
|
|
||||||
|
|
||||||
hash_init(&hash);
|
|
||||||
|
|
||||||
hash_addr(&hash, local);
|
|
||||||
hash_addr(&hash, remote);
|
|
||||||
|
|
||||||
hash_end(&hash);
|
|
||||||
|
|
||||||
return hash;
|
|
||||||
}
|
|
||||||
|
|
||||||
static patty_ax25_sock *sock_by_fd(patty_dict *dict,
|
static patty_ax25_sock *sock_by_fd(patty_dict *dict,
|
||||||
int fd) {
|
int fd) {
|
||||||
return patty_dict_get(dict,
|
return patty_dict_get(dict,
|
||||||
|
@ -175,7 +152,12 @@ static patty_ax25_sock *sock_by_addrpair(patty_dict *dict,
|
||||||
patty_ax25_addr *remote) {
|
patty_ax25_addr *remote) {
|
||||||
patty_dict_slot *slot;
|
patty_dict_slot *slot;
|
||||||
|
|
||||||
uint32_t hash = hash_addrpair(local, remote);
|
uint32_t hash;
|
||||||
|
|
||||||
|
hash_init(&hash);
|
||||||
|
hash_addr(&hash, local);
|
||||||
|
hash_addr(&hash, remote);
|
||||||
|
hash_end(&hash);
|
||||||
|
|
||||||
if ((slot = patty_dict_slot_find(dict, hash)) == NULL) {
|
if ((slot = patty_dict_slot_find(dict, hash)) == NULL) {
|
||||||
errno = EEXIST;
|
errno = EEXIST;
|
||||||
|
@ -230,7 +212,12 @@ static int sock_save_by_addrpair(patty_dict *dict,
|
||||||
patty_ax25_sock *sock,
|
patty_ax25_sock *sock,
|
||||||
patty_ax25_addr *local,
|
patty_ax25_addr *local,
|
||||||
patty_ax25_addr *remote) {
|
patty_ax25_addr *remote) {
|
||||||
uint32_t hash = hash_addrpair(local, remote);
|
uint32_t hash;
|
||||||
|
|
||||||
|
hash_init(&hash);
|
||||||
|
hash_addr(&hash, local);
|
||||||
|
hash_addr(&hash, remote);
|
||||||
|
hash_end(&hash);
|
||||||
|
|
||||||
if (patty_dict_set_with_hash(dict,
|
if (patty_dict_set_with_hash(dict,
|
||||||
sock,
|
sock,
|
||||||
|
@ -246,6 +233,47 @@ error_dict_set_with_hash:
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int sock_delete(patty_ax25_server *server,
|
||||||
|
patty_ax25_sock *sock) {
|
||||||
|
uint32_t hash_established,
|
||||||
|
hash_pending_connect,
|
||||||
|
hash_pending_accept;
|
||||||
|
|
||||||
|
hash_init(&hash_established);
|
||||||
|
hash_addr(&hash_established, &sock->local);
|
||||||
|
hash_addr(&hash_established, &sock->remote);
|
||||||
|
hash_end(&hash_established);
|
||||||
|
|
||||||
|
if (patty_dict_delete_with_hash(server->socks_established, hash_established) < 0) {
|
||||||
|
goto error_dict_delete_established;
|
||||||
|
}
|
||||||
|
|
||||||
|
hash_init(&hash_pending_connect);
|
||||||
|
hash_addr(&hash_pending_connect, &sock->local);
|
||||||
|
hash_end(&hash_pending_connect);
|
||||||
|
|
||||||
|
if (patty_dict_delete_with_hash(server->socks_pending_connect, hash_pending_connect) < 0) {
|
||||||
|
goto error_dict_delete_pending_connect;
|
||||||
|
}
|
||||||
|
|
||||||
|
hash_init(&hash_pending_accept);
|
||||||
|
hash_addr(&hash_pending_accept, &sock->local);
|
||||||
|
hash_end(&hash_pending_accept);
|
||||||
|
|
||||||
|
if (patty_dict_delete(server->socks_by_fd, NULL + sock->fd, sizeof(sock->fd)) < 0) {
|
||||||
|
goto error_dict_delete_by_fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(sock);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
error_dict_delete_by_fd:
|
||||||
|
error_dict_delete_pending_connect:
|
||||||
|
error_dict_delete_established:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
int patty_ax25_server_add_if(patty_ax25_server *server,
|
int patty_ax25_server_add_if(patty_ax25_server *server,
|
||||||
patty_ax25_if *iface) {
|
patty_ax25_if *iface) {
|
||||||
int fd;
|
int fd;
|
||||||
|
@ -299,7 +327,7 @@ int patty_ax25_server_delete_if(patty_ax25_server *server,
|
||||||
server->fd_max--;
|
server->fd_max--;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (patty_dict_delete(server->socks_by_fd, NULL + fd, sizeof(fd)) == NULL) {
|
if (patty_dict_delete(server->socks_by_fd, NULL + fd, sizeof(fd)) < 0) {
|
||||||
goto error_dict_delete;
|
goto error_dict_delete;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -424,48 +452,31 @@ static int server_bind(patty_ax25_server *server,
|
||||||
goto error_sock_by_fd;
|
goto error_sock_by_fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
switch (sock->status) {
|
||||||
* If there is already a local address associated with this socket, then
|
case PATTY_AX25_SOCK_LISTENING:
|
||||||
* that's a problem.
|
case PATTY_AX25_SOCK_ESTABLISHED:
|
||||||
*/
|
|
||||||
if (sock->local.callsign[0] != '\0') {
|
|
||||||
response.ret = -1;
|
response.ret = -1;
|
||||||
response.eno = EINVAL;
|
response.eno = EINVAL;
|
||||||
|
|
||||||
goto error_bound;
|
goto error_invalid_status;
|
||||||
}
|
|
||||||
|
|
||||||
if (patty_dict_get(server->socks_bound,
|
default:
|
||||||
&sock->local,
|
break;
|
||||||
sizeof(sock->local))) {
|
|
||||||
response.ret = -1;
|
|
||||||
response.eno = EADDRINUSE;
|
|
||||||
|
|
||||||
goto error_inuse;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(&sock->local, &request.peer, sizeof(request.peer));
|
memcpy(&sock->local, &request.peer, sizeof(request.peer));
|
||||||
|
|
||||||
if (patty_dict_set(server->socks_bound,
|
response.ret = 0;
|
||||||
&sock->local,
|
response.eno = 0;
|
||||||
sizeof(sock->local),
|
|
||||||
sock) == NULL) {
|
|
||||||
goto error_dict_set;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
error_invalid_status:
|
||||||
|
error_sock_by_fd:
|
||||||
if (write(client, &response, sizeof(response)) < 0) {
|
if (write(client, &response, sizeof(response)) < 0) {
|
||||||
goto error_io;
|
goto error_io;
|
||||||
}
|
}
|
||||||
|
|
||||||
response.ret = 0;
|
|
||||||
response.eno = 0;
|
|
||||||
|
|
||||||
error_inuse:
|
|
||||||
error_bound:
|
|
||||||
error_sock_by_fd:
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
error_dict_set:
|
|
||||||
error_io:
|
error_io:
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -530,6 +541,8 @@ static int server_accept_pty(patty_ax25_server *server,
|
||||||
goto error_ptsname_r;
|
goto error_ptsname_r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sock->type |= PATTY_AX25_SOCK_PTY;
|
||||||
|
|
||||||
response->ret = sock->fd;
|
response->ret = sock->fd;
|
||||||
response->eno = 0;
|
response->eno = 0;
|
||||||
|
|
||||||
|
@ -565,6 +578,8 @@ static int server_accept_unix(patty_ax25_server *server,
|
||||||
goto error_bind;
|
goto error_bind;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sock->type |= PATTY_AX25_SOCK_UNIX;
|
||||||
|
|
||||||
response->ret = sock->fd;
|
response->ret = sock->fd;
|
||||||
response->eno = 0;
|
response->eno = 0;
|
||||||
|
|
||||||
|
@ -603,6 +618,8 @@ static int server_accept(patty_ax25_server *server,
|
||||||
|
|
||||||
sock_init(remote, local->type);
|
sock_init(remote, local->type);
|
||||||
|
|
||||||
|
memcpy(&remote->local, &local->local, sizeof(remote->local));
|
||||||
|
|
||||||
if (local->type & PATTY_AX25_SOCK_PTY) {
|
if (local->type & PATTY_AX25_SOCK_PTY) {
|
||||||
if (server_accept_pty(server, &response, remote) < 0) {
|
if (server_accept_pty(server, &response, remote) < 0) {
|
||||||
goto error_server_accept_pty;
|
goto error_server_accept_pty;
|
||||||
|
@ -613,6 +630,18 @@ static int server_accept(patty_ax25_server *server,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (sock_save_by_addr(server->socks_pending_accept,
|
||||||
|
remote,
|
||||||
|
&local->local) < 0) {
|
||||||
|
goto error_save_by_addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sock_save_by_fd(server->socks_by_fd, remote) < 0) {
|
||||||
|
goto error_save_by_fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
error_sock_by_fd:
|
error_sock_by_fd:
|
||||||
if (write(client, &response, sizeof(response)) < 0) {
|
if (write(client, &response, sizeof(response)) < 0) {
|
||||||
goto error_io;
|
goto error_io;
|
||||||
|
@ -620,6 +649,8 @@ error_sock_by_fd:
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
error_save_by_fd:
|
||||||
|
error_save_by_addr:
|
||||||
error_server_accept_unix:
|
error_server_accept_unix:
|
||||||
error_server_accept_pty:
|
error_server_accept_pty:
|
||||||
free(remote);
|
free(remote);
|
||||||
|
@ -647,23 +678,40 @@ static int server_connect(patty_ax25_server *server,
|
||||||
goto error_sock_by_fd;
|
goto error_sock_by_fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sock->remote.callsign[0] != '\0') {
|
switch (sock->status) {
|
||||||
|
case PATTY_AX25_SOCK_LISTENING:
|
||||||
response.ret = -1;
|
response.ret = -1;
|
||||||
response.eno = EEXIST;
|
response.eno = EINVAL;
|
||||||
|
|
||||||
goto error_exists;
|
goto error_invalid_status;
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PATTY_AX25_SOCK_ESTABLISHED:
|
||||||
|
response.ret = -1;
|
||||||
|
response.eno = EISCONN;
|
||||||
|
|
||||||
|
goto error_invalid_status;
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(&sock->remote, &request.peer, sizeof(request.peer));
|
memcpy(&sock->remote, &request.peer, sizeof(request.peer));
|
||||||
|
|
||||||
if (sock_save_by_addrpair(server->socks_established,
|
if (sock_save_by_addrpair(server->socks_pending_connect,
|
||||||
sock,
|
sock,
|
||||||
&sock->local,
|
&sock->local,
|
||||||
&sock->remote) < 0) {
|
&sock->remote) < 0) {
|
||||||
goto error_sock_save_by_addrpair;
|
goto error_sock_save_by_addrpair;
|
||||||
}
|
}
|
||||||
|
|
||||||
error_exists:
|
response.ret = 0;
|
||||||
|
response.eno = 0;
|
||||||
|
|
||||||
|
error_invalid_status:
|
||||||
error_sock_by_fd:
|
error_sock_by_fd:
|
||||||
if (write(client, &response, sizeof(response)) < 0) {
|
if (write(client, &response, sizeof(response)) < 0) {
|
||||||
goto error_io;
|
goto error_io;
|
||||||
|
@ -676,3 +724,50 @@ error_io:
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int server_close(patty_ax25_server *server,
|
||||||
|
int client) {
|
||||||
|
patty_ax25_call_close_request request;
|
||||||
|
patty_ax25_call_close_response response;
|
||||||
|
|
||||||
|
patty_ax25_sock *sock;
|
||||||
|
|
||||||
|
if (read(client, &request, sizeof(request)) < 0) {
|
||||||
|
goto error_io;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((sock = sock_by_fd(server->socks_by_fd, request.socket)) == NULL) {
|
||||||
|
response.ret = -1;
|
||||||
|
response.eno = EBADF;
|
||||||
|
|
||||||
|
goto error_sock_by_fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sock_delete(server, sock) < 0) {
|
||||||
|
response.ret = -1;
|
||||||
|
response.eno = EBADF;
|
||||||
|
|
||||||
|
goto error_sock_delete;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (close(request.socket) < 0) {
|
||||||
|
response.ret = -1;
|
||||||
|
response.eno = errno;
|
||||||
|
|
||||||
|
goto error_close;
|
||||||
|
}
|
||||||
|
|
||||||
|
response.ret = 0;
|
||||||
|
response.eno = 0;
|
||||||
|
|
||||||
|
error_close:
|
||||||
|
error_sock_delete:
|
||||||
|
error_sock_by_fd:
|
||||||
|
if (write(client, &response, sizeof(response)) < 0) {
|
||||||
|
goto error_io;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
error_io:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue