Massive refactoring afoot
This commit is contained in:
parent
fa3f4a2e0e
commit
d2e278f715
11 changed files with 630 additions and 443 deletions
|
@ -8,6 +8,11 @@
|
|||
#include <patty/list.h>
|
||||
#include <patty/dict.h>
|
||||
|
||||
#define PATTY_AX25_ADDRESS_SIZE 7
|
||||
#define PATTY_AX25_CALLSIGN_LEN 6
|
||||
#define PATTY_AX25_IF_NAME_SIZE 8
|
||||
#define PATTY_AX25_SOCK_PATH_SIZE 256
|
||||
|
||||
#pragma pack(push)
|
||||
#pragma pack(1)
|
||||
|
||||
|
@ -24,14 +29,11 @@ typedef struct _patty_ax25_if patty_ax25_if;
|
|||
#include <patty/ax25/proto.h>
|
||||
#include <patty/ax25/frame.h>
|
||||
#include <patty/ax25/server.h>
|
||||
#include <patty/ax25/call.h>
|
||||
#include <patty/ax25/if.h>
|
||||
|
||||
#define PATTY_AX25_ADDRESS_SIZE 7
|
||||
#define PATTY_AX25_CALLSIGN_LEN 6
|
||||
|
||||
enum patty_ax25_sock_status {
|
||||
PATTY_AX25_SOCK_CLOSED,
|
||||
PATTY_AX25_SOCK_OPEN,
|
||||
PATTY_AX25_SOCK_LISTENING,
|
||||
PATTY_AX25_SOCK_ESTABLISHED
|
||||
};
|
||||
|
@ -42,15 +44,18 @@ enum patty_ax25_sock_mode {
|
|||
PATTY_AX25_SOCK_SABME
|
||||
};
|
||||
|
||||
enum patty_ax25_sock_opts {
|
||||
PATTY_AX25_SOCK_NONBLOCK = 1 << 0,
|
||||
PATTY_AX25_SOCK_PTY = 1 << 1
|
||||
enum patty_ax25_sock_type {
|
||||
PATTY_AX25_SOCK_NONE,
|
||||
PATTY_AX25_SOCK_UNIX = 1 << 0,
|
||||
PATTY_AX25_SOCK_PTY = 1 << 1,
|
||||
PATTY_AX25_SOCK_RAW = 1 << 2,
|
||||
PATTY_AX25_SOCK_NONBLOCK = 1 << 3
|
||||
};
|
||||
|
||||
typedef struct _patty_ax25_sock {
|
||||
enum patty_ax25_sock_status status;
|
||||
enum patty_ax25_sock_mode mode;
|
||||
enum patty_ax25_sock_opts opts;
|
||||
enum patty_ax25_sock_type type;
|
||||
|
||||
time_t timer_ack,
|
||||
timer_response,
|
||||
|
@ -64,6 +69,7 @@ typedef struct _patty_ax25_sock {
|
|||
seq_recv;
|
||||
|
||||
int fd;
|
||||
char path[PATTY_AX25_SOCK_PATH_SIZE];
|
||||
|
||||
patty_ax25_if *iface;
|
||||
|
||||
|
@ -83,39 +89,4 @@ int patty_ax25_ntop(const patty_ax25_addr *addr,
|
|||
uint8_t *ssid,
|
||||
size_t len);
|
||||
|
||||
int patty_ax25_open(int server,
|
||||
const char *ifname);
|
||||
|
||||
int patty_ax25_socket(int server,
|
||||
int sockopts);
|
||||
|
||||
int patty_ax25_bind(int server,
|
||||
int socket,
|
||||
patty_ax25_addr *addr);
|
||||
|
||||
int patty_ax25_listen(int server,
|
||||
int socket);
|
||||
|
||||
int patty_ax25_accept(int server,
|
||||
int socket);
|
||||
|
||||
int patty_ax25_connect(int server,
|
||||
int socket,
|
||||
patty_ax25_addr *addr);
|
||||
|
||||
int patty_ax25_close(int server,
|
||||
int socket);
|
||||
|
||||
ssize_t patty_ax25_sendto(int server,
|
||||
int socket,
|
||||
const void *buf,
|
||||
size_t len,
|
||||
patty_ax25_addr *addr);
|
||||
|
||||
int patty_ax25_recvfrom(int server,
|
||||
int socket,
|
||||
void *buf,
|
||||
size_t len,
|
||||
patty_ax25_addr *addr);
|
||||
|
||||
#endif /* _PATTY_AX25_H */
|
||||
|
|
134
include/patty/ax25/call.h
Normal file
134
include/patty/ax25/call.h
Normal file
|
@ -0,0 +1,134 @@
|
|||
#ifndef _PATTY_AX25_CALL_H
|
||||
#define _PATTY_AX25_CALL_H
|
||||
|
||||
enum patty_ax25_call {
|
||||
PATTY_AX25_CALL_UNKNOWN,
|
||||
PATTY_AX25_CALL_SOCKET,
|
||||
PATTY_AX25_CALL_BIND,
|
||||
PATTY_AX25_CALL_LISTEN,
|
||||
PATTY_AX25_CALL_ACCEPT,
|
||||
PATTY_AX25_CALL_CONNECT,
|
||||
PATTY_AX25_CALL_CLOSE,
|
||||
PATTY_AX25_CALL_SENDTO,
|
||||
PATTY_AX25_CALL_RECVFROM
|
||||
};
|
||||
|
||||
/*
|
||||
* socket()
|
||||
*/
|
||||
typedef struct _patty_ax25_call_socket_request {
|
||||
int type;
|
||||
} patty_ax25_call_socket_request;
|
||||
|
||||
typedef struct _patty_ax25_response_socket {
|
||||
int ret;
|
||||
int eno;
|
||||
} patty_ax25_call_socket_response;
|
||||
|
||||
int patty_ax25_call_socket(int server,
|
||||
int type);
|
||||
|
||||
/*
|
||||
* bind()
|
||||
*/
|
||||
typedef struct _patty_ax25_call_bind_request {
|
||||
int socket;
|
||||
patty_ax25_addr peer;
|
||||
} patty_ax25_call_bind_request;
|
||||
|
||||
typedef struct _patty_ax25_call_bind_response {
|
||||
int ret;
|
||||
int eno;
|
||||
} patty_ax25_call_bind_response;
|
||||
|
||||
int patty_ax25_call_bind(int server,
|
||||
int socket,
|
||||
patty_ax25_addr *addr);
|
||||
|
||||
/*
|
||||
* listen()
|
||||
*/
|
||||
typedef struct _patty_ax25_call_listen_request {
|
||||
int socket;
|
||||
} patty_ax25_call_listen_request;
|
||||
|
||||
typedef struct _patty_ax25_call_listen_response {
|
||||
int ret;
|
||||
int eno;
|
||||
} patty_ax25_call_listen_response;
|
||||
|
||||
int patty_ax25_call_listen(int server,
|
||||
int socket);
|
||||
|
||||
/*
|
||||
* accept()
|
||||
*/
|
||||
typedef struct _patty_ax25_call_accept_request {
|
||||
int socket;
|
||||
} patty_ax25_call_accept_request;
|
||||
|
||||
typedef struct _patty_ax25_call_accept_response {
|
||||
int ret;
|
||||
int eno;
|
||||
char path[PATTY_AX25_SOCK_PATH_SIZE];
|
||||
patty_ax25_addr peer;
|
||||
} patty_ax25_call_accept_response;
|
||||
|
||||
int patty_ax25_call_accept(int server,
|
||||
int socket,
|
||||
patty_ax25_addr *peer,
|
||||
char *path);
|
||||
|
||||
/*
|
||||
* connect()
|
||||
*/
|
||||
typedef struct _patty_ax25_call_connect_request {
|
||||
int socket;
|
||||
patty_ax25_addr peer;
|
||||
} patty_ax25_call_connect_request;
|
||||
|
||||
typedef struct _patty_ax25_call_connect_response {
|
||||
int ret;
|
||||
int eno;
|
||||
char path[PATTY_AX25_SOCK_PATH_SIZE];
|
||||
} patty_ax25_call_connect_response;
|
||||
|
||||
int patty_ax25_call_connect(int server,
|
||||
int socket,
|
||||
patty_ax25_addr *peer,
|
||||
char *path);
|
||||
|
||||
/*
|
||||
* close()
|
||||
*/
|
||||
typedef struct _patty_ax25_call_close_request {
|
||||
int socket;
|
||||
} patty_ax25_call_close_request;
|
||||
|
||||
typedef struct _patty_ax25_call_close_response {
|
||||
int ret;
|
||||
int eno;
|
||||
} patty_ax25_call_close_response;
|
||||
|
||||
int patty_ax25_call_close(int server,
|
||||
int socket);
|
||||
|
||||
/*
|
||||
* sendto()
|
||||
*/
|
||||
ssize_t patty_ax25_call_sendto(int server,
|
||||
int socket,
|
||||
const void *buf,
|
||||
size_t len,
|
||||
patty_ax25_addr *addr);
|
||||
|
||||
/*
|
||||
* recvfrom()
|
||||
*/
|
||||
int patty_ax25_call_recvfrom(int server,
|
||||
int socket,
|
||||
void *buf,
|
||||
size_t len,
|
||||
patty_ax25_addr *addr);
|
||||
|
||||
#endif /* _PATTY_AX25_CALL_H */
|
|
@ -1,21 +0,0 @@
|
|||
#ifndef _PATTY_AX25_CLIENT_H
|
||||
#define _PATTY_AX25_CLIENT_H
|
||||
|
||||
enum patty_ax25_client_call {
|
||||
PATTY_AX25_CLIENT_UNKNOWN,
|
||||
PATTY_AX25_CLIENT_SOCKET,
|
||||
PATTY_AX25_CLIENT_BIND,
|
||||
PATTY_AX25_CLIENT_LISTEN,
|
||||
PATTY_AX25_CLIENT_ACCEPT,
|
||||
PATTY_AX25_CLIENT_CONNECT,
|
||||
PATTY_AX25_CLIENT_CLOSE,
|
||||
PATTY_AX25_CLIENT_SENDTO,
|
||||
PATTY_AX25_CLIENT_RECVFROM
|
||||
};
|
||||
|
||||
ssize_t patty_ax25_client_send(int fd,
|
||||
enum patty_ax25_client_call call,
|
||||
void *data,
|
||||
size_t len);
|
||||
|
||||
#endif /* _PATTY_AX25_CLIENT_H */
|
|
@ -48,17 +48,4 @@ 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);
|
||||
|
||||
patty_ax25_if *patty_ax25_get_if(patty_ax25_server *server,
|
||||
const char *name);
|
||||
|
||||
int patty_ax25_if_each(patty_ax25_server *server,
|
||||
int (*callback)(patty_ax25_if *, void *),
|
||||
void *ctx);
|
||||
|
||||
int patty_ax25_add_if(patty_ax25_server *server,
|
||||
patty_ax25_if *iface);
|
||||
|
||||
int patty_ax25_delete_if(patty_ax25_server *server,
|
||||
patty_ax25_if *iface);
|
||||
|
||||
#endif /* _PATTY_AX25_IF_H */
|
||||
|
|
|
@ -1,19 +1,7 @@
|
|||
#ifndef _PATTY_AX25_SERVER_H
|
||||
#define _PATTY_AX25_SERVER_H
|
||||
|
||||
typedef struct _patty_ax25_server {
|
||||
patty_list *ifaces;
|
||||
|
||||
patty_dict *socks,
|
||||
*socks_by_addrpair;
|
||||
|
||||
int fd,
|
||||
fd_max;
|
||||
|
||||
fd_set fds,
|
||||
fds_r,
|
||||
fds_w;
|
||||
} patty_ax25_server;
|
||||
typedef struct _patty_ax25_server patty_ax25_server;
|
||||
|
||||
int patty_ax25_server_init(patty_ax25_server *server);
|
||||
|
||||
|
@ -21,4 +9,17 @@ void patty_ax25_server_stop(patty_ax25_server *server);
|
|||
|
||||
int patty_ax25_server_run(patty_ax25_server *server);
|
||||
|
||||
int patty_ax25_server_add_if(patty_ax25_server *server,
|
||||
patty_ax25_if *iface);
|
||||
|
||||
int patty_ax25_server_delete_if(patty_ax25_server *server,
|
||||
patty_ax25_if *iface);
|
||||
|
||||
patty_ax25_if *patty_ax25_server_get_if(patty_ax25_server *server,
|
||||
const char *name);
|
||||
|
||||
int patty_ax25_server_each_if(patty_ax25_server *server,
|
||||
int (*callback)(patty_ax25_if *, void *),
|
||||
void *ctx);
|
||||
|
||||
#endif /* _PATTY_AX25_SERVER_H */
|
||||
|
|
|
@ -5,25 +5,24 @@
|
|||
#include <sys/types.h>
|
||||
|
||||
typedef struct _patty_list_item {
|
||||
struct _patty_list_item * prev;
|
||||
struct _patty_list_item * next;
|
||||
struct _patty_list_item *prev,
|
||||
*next;
|
||||
|
||||
void * value;
|
||||
void *value;
|
||||
} patty_list_item;
|
||||
|
||||
typedef struct _patty_list {
|
||||
uint64_t size;
|
||||
uint64_t length;
|
||||
|
||||
patty_list_item * first;
|
||||
patty_list_item * last;
|
||||
patty_list_item *first,
|
||||
*last;
|
||||
} patty_list;
|
||||
|
||||
typedef struct _patty_list_iterator {
|
||||
patty_list *list;
|
||||
|
||||
size_t index;
|
||||
patty_list_item * item;
|
||||
patty_list_item *item;
|
||||
} patty_list_iterator;
|
||||
|
||||
typedef void (*patty_list_callback)(void *item, void *ctx);
|
||||
|
@ -44,6 +43,8 @@ void *patty_list_last(patty_list *list);
|
|||
|
||||
void *patty_list_pop(patty_list *list);
|
||||
|
||||
void *patty_list_shift(patty_list *list);
|
||||
|
||||
void *patty_list_splice(patty_list *list, off_t index);
|
||||
|
||||
void *patty_list_insert(patty_list *list, off_t index);
|
||||
|
|
|
@ -7,11 +7,10 @@ CC = $(CROSS)cc
|
|||
CFLAGS = $(CGFLAGS) -fPIC -Wall -O2 -I$(INCLUDE_PATH)
|
||||
LDFLAGS =
|
||||
|
||||
HEADERS = kiss.h ax25.h ax25/if.h ax25/macros.h ax25/proto.h \
|
||||
HEADERS = kiss.h ax25.h ax25/if.h ax25/macros.h ax25/proto.h ax25/call.h \
|
||||
ax25/frame.h ax25/server.h list.h hash.h dict.h
|
||||
|
||||
OBJS = kiss.o ax25.o if.o frame.o \
|
||||
server.o list.o hash.o dict.o
|
||||
OBJS = kiss.o ax25.o if.o call.o frame.o server.o list.o hash.o dict.o
|
||||
|
||||
EXAMPLES = decode ptmx
|
||||
|
||||
|
|
12
src/ax25.c
12
src/ax25.c
|
@ -5,18 +5,6 @@
|
|||
|
||||
#include <patty/ax25.h>
|
||||
|
||||
enum remote_call {
|
||||
PATTY_AX25_UNKNOWN,
|
||||
PATTY_AX25_SOCKET,
|
||||
PATTY_AX25_BIND,
|
||||
PATTY_AX25_LISTEN,
|
||||
PATTY_AX25_ACCEPT,
|
||||
PATTY_AX25_CONNECT,
|
||||
PATTY_AX25_CLOSE,
|
||||
PATTY_AX25_SENDTO,
|
||||
PATTY_AX25_RECVFROM
|
||||
};
|
||||
|
||||
int patty_ax25_pton(const char *callsign,
|
||||
uint8_t ssid,
|
||||
patty_ax25_addr *addr) {
|
||||
|
|
114
src/if.c
114
src/if.c
|
@ -221,117 +221,3 @@ error_ntop:
|
|||
return -1;
|
||||
}
|
||||
|
||||
patty_ax25_if *patty_ax25_get_if(patty_ax25_server *server,
|
||||
const char *name) {
|
||||
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 (strncmp(iface->name, name, sizeof(iface->name)) == 0) {
|
||||
patty_list_finish(iter);
|
||||
|
||||
return iface;
|
||||
}
|
||||
}
|
||||
|
||||
patty_list_finish(iter);
|
||||
|
||||
error_list_start:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int patty_ax25_if_each(patty_ax25_server *server,
|
||||
int (*callback)(patty_ax25_if *, void *),
|
||||
void *ctx) {
|
||||
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 (callback(iface, ctx) < 0) {
|
||||
goto error_callback;
|
||||
}
|
||||
}
|
||||
|
||||
patty_list_finish(iter);
|
||||
|
||||
return 0;
|
||||
|
||||
error_callback:
|
||||
patty_list_finish(iter);
|
||||
|
||||
error_list_start:
|
||||
return -1;
|
||||
}
|
||||
|
||||
int patty_ax25_add_if(patty_ax25_server *server,
|
||||
patty_ax25_if *iface) {
|
||||
int fd;
|
||||
|
||||
if ((fd = patty_kiss_tnc_fd(iface->tnc)) >= 0) {
|
||||
FD_SET(fd, &server->fds);
|
||||
|
||||
if (server->fd_max < fd + 1) {
|
||||
server->fd_max = fd + 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (patty_dict_set(server->socks, NULL + fd, sizeof(fd), iface) == NULL) {
|
||||
goto error_dict_set;
|
||||
}
|
||||
|
||||
if (patty_list_append(server->ifaces, iface) == NULL) {
|
||||
goto error_list_append;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
error_list_append:
|
||||
error_dict_set:
|
||||
return -1;
|
||||
}
|
||||
|
||||
int patty_ax25_delete_if(patty_ax25_server *server,
|
||||
patty_ax25_if *iface) {
|
||||
patty_list_item *item = server->ifaces->first;
|
||||
|
||||
int fd, i = 0;
|
||||
|
||||
while (item) {
|
||||
if (item->value == iface) {
|
||||
if (patty_list_splice(server->ifaces, i) == NULL) {
|
||||
goto error_list_splice;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
item = item->next;
|
||||
i++;
|
||||
}
|
||||
|
||||
if ((fd = patty_kiss_tnc_fd(iface->tnc)) >= 0) {
|
||||
FD_CLR(fd, &server->fds);
|
||||
|
||||
if (server->fd_max == fd) {
|
||||
server->fd_max--;
|
||||
}
|
||||
|
||||
if (patty_dict_delete(server->socks, NULL + fd, sizeof(fd)) == NULL) {
|
||||
goto error_dict_delete;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
error_dict_delete:
|
||||
error_list_splice:
|
||||
return -1;
|
||||
}
|
||||
|
|
65
src/list.c
65
src/list.c
|
@ -12,7 +12,6 @@ patty_list *patty_list_new() {
|
|||
}
|
||||
|
||||
list->length = 0;
|
||||
list->size = 0;
|
||||
list->first = NULL;
|
||||
list->last = NULL;
|
||||
|
||||
|
@ -92,29 +91,53 @@ void *patty_list_last(patty_list *list) {
|
|||
}
|
||||
|
||||
void *patty_list_pop(patty_list *list) {
|
||||
patty_list_item *item = list->first;
|
||||
patty_list_item *last = NULL;
|
||||
void *value;
|
||||
patty_list_item *item = list->last;
|
||||
|
||||
while (item != NULL) {
|
||||
if (item->next == NULL) {
|
||||
void *ret = item->value;
|
||||
|
||||
if (last == NULL) {
|
||||
list->first = NULL;
|
||||
} else {
|
||||
last->next = NULL;
|
||||
}
|
||||
|
||||
free(item);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
last = item;
|
||||
item = item->next;
|
||||
if (item == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
if (list->last->prev) {
|
||||
list->last = list->last->prev;
|
||||
list->last->next = NULL;
|
||||
} else {
|
||||
list->first = NULL;
|
||||
list->last = NULL;
|
||||
}
|
||||
|
||||
list->length--;
|
||||
|
||||
value = item->value;
|
||||
|
||||
free(item);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
void *patty_list_shift(patty_list *list) {
|
||||
void *value;
|
||||
patty_list_item *item = list->first;
|
||||
|
||||
if (item == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (list->first->next) {
|
||||
list->first = list->first->next;
|
||||
list->first->prev = NULL;
|
||||
} else {
|
||||
list->first = NULL;
|
||||
list->last = NULL;
|
||||
}
|
||||
|
||||
list->length--;
|
||||
|
||||
value = item->value;
|
||||
|
||||
free(item);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
void *patty_list_splice(patty_list *list, off_t index) {
|
||||
|
|
610
src/server.c
610
src/server.c
|
@ -1,3 +1,4 @@
|
|||
#define _GNU_SOURCE
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
@ -9,6 +10,22 @@
|
|||
|
||||
#include <patty/ax25.h>
|
||||
|
||||
struct _patty_ax25_server {
|
||||
patty_list *ifaces;
|
||||
|
||||
patty_dict *socks,
|
||||
*socks_by_addrpair,
|
||||
*socks_bound;
|
||||
|
||||
int fd_max;
|
||||
|
||||
fd_set fds_watch,
|
||||
fds_r,
|
||||
fds_w;
|
||||
|
||||
patty_list *pending_accept;
|
||||
};
|
||||
|
||||
int patty_ax25_server_init(patty_ax25_server *server) {
|
||||
memset(server, '\0', sizeof(*server));
|
||||
|
||||
|
@ -24,8 +41,22 @@ int patty_ax25_server_init(patty_ax25_server *server) {
|
|||
goto error_dict_new_socks_by_addrpair;
|
||||
}
|
||||
|
||||
if ((server->socks_bound = patty_dict_new()) == NULL) {
|
||||
goto error_dict_new_socks_bound;
|
||||
}
|
||||
|
||||
if ((server->pending_accept = patty_list_new()) == NULL) {
|
||||
goto error_list_new_pending_accept;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
error_list_new_pending_accept:
|
||||
patty_dict_destroy(server->socks_bound);
|
||||
|
||||
error_dict_new_socks_bound:
|
||||
patty_dict_destroy(server->socks_by_addrpair);
|
||||
|
||||
error_dict_new_socks_by_addrpair:
|
||||
patty_dict_destroy(server->socks);
|
||||
|
||||
|
@ -46,15 +77,16 @@ void patty_ax25_server_stop(patty_ax25_server *server) {
|
|||
patty_dict_destroy(server->socks_by_addrpair);
|
||||
patty_dict_destroy(server->socks);
|
||||
|
||||
patty_ax25_if_each(server, destroy_if, NULL);
|
||||
patty_ax25_server_each_if(server, destroy_if, NULL);
|
||||
patty_list_destroy(server->ifaces);
|
||||
}
|
||||
|
||||
static void sock_init(patty_ax25_sock *sock) {
|
||||
static void sock_init(patty_ax25_sock *sock, enum patty_ax25_sock_type type) {
|
||||
memset(sock, '\0', sizeof(*sock));
|
||||
|
||||
sock->status = PATTY_AX25_SOCK_OPEN;
|
||||
sock->status = PATTY_AX25_SOCK_CLOSED;
|
||||
sock->mode = PATTY_AX25_SOCK_DM;
|
||||
sock->type = type;
|
||||
sock->n_maxlen = PATTY_AX25_FRAME_DEFAULT_MAXLEN;
|
||||
sock->n_window = PATTY_AX25_FRAME_DEFAULT_WINDOW;
|
||||
}
|
||||
|
@ -123,28 +155,6 @@ error_dict_set:
|
|||
return -1;
|
||||
}
|
||||
|
||||
static int server_open(patty_ax25_server *server, const char *ifname) {
|
||||
patty_ax25_sock *sock;
|
||||
|
||||
if ((sock = malloc(sizeof(*sock))) == NULL) {
|
||||
goto error_malloc_sock;
|
||||
}
|
||||
|
||||
sock_init(sock);
|
||||
|
||||
if ((sock->iface = patty_ax25_get_if(server, ifname)) == NULL) {
|
||||
goto error_get_if;
|
||||
}
|
||||
|
||||
return sock_save(server, sock);
|
||||
|
||||
error_get_if:
|
||||
free(sock);
|
||||
|
||||
error_malloc_sock:
|
||||
return -1;
|
||||
}
|
||||
|
||||
static patty_ax25_sock *sock_by_fd(patty_ax25_server *server, int fd) {
|
||||
patty_ax25_sock *sock;
|
||||
|
||||
|
@ -186,175 +196,6 @@ error_dict_slot_find:
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static int server_socket_pty(patty_ax25_server *server,
|
||||
patty_ax25_sock *sock,
|
||||
int client) {
|
||||
int fd;
|
||||
char name[64];
|
||||
size_t len;
|
||||
|
||||
if ((fd = open("/dev/ptmx", O_RDWR)) < 0) {
|
||||
goto error_open;
|
||||
}
|
||||
|
||||
if (grantpt(fd) < 0) {
|
||||
goto error_grantpt;
|
||||
}
|
||||
|
||||
if (unlockpt(fd) < 0) {
|
||||
goto error_unlockpt;
|
||||
}
|
||||
|
||||
if (ptsname_r(fd, name, sizeof(name)) < 0) {
|
||||
goto error_ptsname_r;
|
||||
}
|
||||
|
||||
len = strnlen(name, sizeof(name) - 1);
|
||||
|
||||
if (write(client, name, sizeof(len)) < 0) {
|
||||
goto error_write;
|
||||
}
|
||||
|
||||
if (write(client, name, len) < 0) {
|
||||
goto error_write;
|
||||
}
|
||||
|
||||
return sock->fd = fd;
|
||||
|
||||
error_write:
|
||||
error_ptsname_r:
|
||||
error_unlockpt:
|
||||
error_grantpt:
|
||||
close(fd);
|
||||
|
||||
error_open:
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int server_socket_unix(patty_ax25_server *server,
|
||||
patty_ax25_sock *sock,
|
||||
int client) {
|
||||
int fd;
|
||||
char name[256];
|
||||
size_t len;
|
||||
|
||||
struct sockaddr_un addr;
|
||||
|
||||
if ((fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) {
|
||||
goto error_socket;
|
||||
}
|
||||
|
||||
if (snprintf(name, sizeof(name), "/var/run/patty/%d.sock", fd) < 0) {
|
||||
goto error_snprintf_name;
|
||||
}
|
||||
|
||||
len = strnlen(name, sizeof(name));
|
||||
|
||||
addr.sun_family = AF_UNIX;
|
||||
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
strncpy(addr.sun_path, name, sizeof(addr.sun_path));
|
||||
|
||||
if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
|
||||
goto error_bind;
|
||||
}
|
||||
|
||||
if (write(client, &len, sizeof(len)) < 0) {
|
||||
goto error_write;
|
||||
}
|
||||
|
||||
if (write(client, name, len) < 0) {
|
||||
goto error_write;
|
||||
}
|
||||
|
||||
return sock->fd = fd;
|
||||
|
||||
error_write:
|
||||
error_bind:
|
||||
error_snprintf_name:
|
||||
close(fd);
|
||||
|
||||
error_socket:
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int server_socket(patty_ax25_server *server,
|
||||
int client,
|
||||
int sockopts) {
|
||||
patty_ax25_sock *sock;
|
||||
|
||||
if ((sock = malloc(sizeof(*sock))) == NULL) {
|
||||
goto error_malloc_sock;
|
||||
}
|
||||
|
||||
sock_init(sock);
|
||||
|
||||
if (sockopts & PATTY_AX25_SOCK_PTY) {
|
||||
if (server_socket_pty(server, sock, client) < 0) {
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
return sock->fd;
|
||||
|
||||
error:
|
||||
free(sock);
|
||||
|
||||
error_malloc_sock:
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int server_bind(patty_ax25_server *server,
|
||||
int socket,
|
||||
patty_ax25_addr *addr) {
|
||||
patty_ax25_sock *sock;
|
||||
|
||||
if ((sock = sock_get_fd(server, socket)) == NULL) {
|
||||
goto error_sock_get_fd;
|
||||
}
|
||||
|
||||
/*
|
||||
* If there is already a local address associated with this socket, then
|
||||
* that's a problem.
|
||||
*/
|
||||
if (sock->local.callsign[0] != '\0') {
|
||||
errno = EADDRINUSE;
|
||||
|
||||
goto error_exists;
|
||||
}
|
||||
|
||||
memcpy(&sock->local, addr, sizeof(*addr));
|
||||
|
||||
return 0;
|
||||
|
||||
error_exists:
|
||||
error_sock_get_fd:
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int server_listen(patty_ax25_server *server,
|
||||
int socket) {
|
||||
patty_ax25_sock *sock;
|
||||
|
||||
if ((sock = sock_get_fd(server, socket)) == NULL) {
|
||||
errno = EBADF;
|
||||
|
||||
goto error_sock_get_fd;
|
||||
}
|
||||
|
||||
if (sock->local.callsign[0] == '\0') {
|
||||
errno = EINVAL;
|
||||
|
||||
goto error_invalid_fd;
|
||||
}
|
||||
|
||||
errno = ENOSYS;
|
||||
|
||||
error_invalid_fd:
|
||||
error_sock_get_fd:
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int server_connect(patty_ax25_server *server,
|
||||
int socket,
|
||||
patty_ax25_addr *addr) {
|
||||
|
@ -379,8 +220,385 @@ error_sock_get_fd:
|
|||
return -1;
|
||||
}
|
||||
|
||||
static int server_accept(patty_ax25_server *server, int socket) {
|
||||
errno = ENOSYS;
|
||||
int patty_ax25_server_add_if(patty_ax25_server *server,
|
||||
patty_ax25_if *iface) {
|
||||
int fd;
|
||||
|
||||
if ((fd = patty_kiss_tnc_fd(iface->tnc)) >= 0) {
|
||||
FD_SET(fd, &server->fds_watch);
|
||||
|
||||
if (server->fd_max < fd + 1) {
|
||||
server->fd_max = fd + 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (patty_dict_set(server->socks, NULL + fd, sizeof(fd), iface) == NULL) {
|
||||
goto error_dict_set;
|
||||
}
|
||||
|
||||
if (patty_list_append(server->ifaces, iface) == NULL) {
|
||||
goto error_list_append;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
error_list_append:
|
||||
error_dict_set:
|
||||
return -1;
|
||||
}
|
||||
|
||||
int patty_ax25_server_delete_if(patty_ax25_server *server,
|
||||
patty_ax25_if *iface) {
|
||||
patty_list_item *item = server->ifaces->first;
|
||||
|
||||
int fd, i = 0;
|
||||
|
||||
while (item) {
|
||||
if (item->value == iface) {
|
||||
if (patty_list_splice(server->ifaces, i) == NULL) {
|
||||
goto error_list_splice;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
item = item->next;
|
||||
i++;
|
||||
}
|
||||
|
||||
if ((fd = patty_kiss_tnc_fd(iface->tnc)) >= 0) {
|
||||
FD_CLR(fd, &server->fds_watch);
|
||||
|
||||
if (server->fd_max == fd) {
|
||||
server->fd_max--;
|
||||
}
|
||||
|
||||
if (patty_dict_delete(server->socks, NULL + fd, sizeof(fd)) == NULL) {
|
||||
goto error_dict_delete;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
error_dict_delete:
|
||||
error_list_splice:
|
||||
return -1;
|
||||
}
|
||||
|
||||
patty_ax25_if *patty_ax25_server_get_if(patty_ax25_server *server,
|
||||
const char *name) {
|
||||
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 (strncmp(iface->name, name, sizeof(iface->name)) == 0) {
|
||||
patty_list_finish(iter);
|
||||
|
||||
return iface;
|
||||
}
|
||||
}
|
||||
|
||||
patty_list_finish(iter);
|
||||
|
||||
error_list_start:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int patty_ax25_server_each_if(patty_ax25_server *server,
|
||||
int (*callback)(patty_ax25_if *, void *),
|
||||
void *ctx) {
|
||||
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 (callback(iface, ctx) < 0) {
|
||||
goto error_callback;
|
||||
}
|
||||
}
|
||||
|
||||
patty_list_finish(iter);
|
||||
|
||||
return 0;
|
||||
|
||||
error_callback:
|
||||
patty_list_finish(iter);
|
||||
|
||||
error_list_start:
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int server_socket(patty_ax25_server *server,
|
||||
int client) {
|
||||
patty_ax25_call_socket_request request;
|
||||
patty_ax25_call_socket_response response;
|
||||
|
||||
patty_ax25_sock *sock;
|
||||
|
||||
if ((sock = malloc(sizeof(*sock))) == NULL) {
|
||||
goto error_malloc_sock;
|
||||
}
|
||||
|
||||
sock_init(sock, request.type);
|
||||
|
||||
if ((sock->fd = open("/dev/null", O_RDWR)) < 0) {
|
||||
goto error_io;
|
||||
}
|
||||
|
||||
if (read(client, &request, sizeof(request)) < 0) {
|
||||
goto error_io;
|
||||
}
|
||||
|
||||
response.ret = sock->fd;
|
||||
response.eno = 0;
|
||||
|
||||
if (sock_save(server, sock) < 0) {
|
||||
response.ret = -1;
|
||||
response.eno = errno;
|
||||
|
||||
goto error_sock_save;
|
||||
}
|
||||
|
||||
error_sock_save:
|
||||
if (write(client, &response, sizeof(response)) < 0) {
|
||||
goto error_io;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
error_io:
|
||||
free(sock);
|
||||
|
||||
error_malloc_sock:
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int server_bind(patty_ax25_server *server,
|
||||
int client) {
|
||||
patty_ax25_call_bind_request request;
|
||||
patty_ax25_call_bind_response response;
|
||||
|
||||
patty_ax25_sock *sock;
|
||||
|
||||
if (read(client, &request, sizeof(request)) < 0) {
|
||||
goto error_io;
|
||||
}
|
||||
|
||||
if ((sock = sock_get_fd(server, request.socket)) == NULL) {
|
||||
response.ret = -1;
|
||||
response.eno = EBADF;
|
||||
|
||||
goto error_sock_get_fd;
|
||||
}
|
||||
|
||||
/*
|
||||
* If there is already a local address associated with this socket, then
|
||||
* that's a problem.
|
||||
*/
|
||||
if (sock->local.callsign[0] != '\0') {
|
||||
response.ret = -1;
|
||||
response.eno = EINVAL;
|
||||
|
||||
goto error_bound;
|
||||
}
|
||||
|
||||
if (patty_dict_get(server->socks_bound,
|
||||
&sock->local,
|
||||
sizeof(sock->local))) {
|
||||
response.ret = -1;
|
||||
response.eno = EADDRINUSE;
|
||||
|
||||
goto error_inuse;
|
||||
}
|
||||
|
||||
memcpy(&sock->local, &request.peer, sizeof(request.peer));
|
||||
|
||||
if (patty_dict_set(server->socks_bound,
|
||||
&sock->local,
|
||||
sizeof(sock->local),
|
||||
sock) == NULL) {
|
||||
goto error_dict_set;
|
||||
}
|
||||
|
||||
if (write(client, &response, sizeof(response)) < 0) {
|
||||
goto error_io;
|
||||
}
|
||||
|
||||
response.ret = 0;
|
||||
response.eno = 0;
|
||||
|
||||
error_inuse:
|
||||
error_bound:
|
||||
error_sock_get_fd:
|
||||
return 0;
|
||||
|
||||
error_dict_set:
|
||||
error_io:
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int server_listen(patty_ax25_server *server,
|
||||
int client) {
|
||||
patty_ax25_call_listen_request request;
|
||||
patty_ax25_call_listen_response response;
|
||||
|
||||
patty_ax25_sock *sock;
|
||||
|
||||
if (read(client, &request, sizeof(request)) < 0) {
|
||||
goto error_io;
|
||||
}
|
||||
|
||||
if ((sock = sock_get_fd(server, request.socket)) == NULL) {
|
||||
response.ret = -1;
|
||||
response.eno = EBADF;
|
||||
|
||||
goto error_sock_get_fd;
|
||||
}
|
||||
|
||||
if (sock->local.callsign[0] == '\0') {
|
||||
response.eno = EINVAL;
|
||||
|
||||
goto error_invalid_fd;
|
||||
}
|
||||
|
||||
sock->status = PATTY_AX25_SOCK_LISTENING;
|
||||
|
||||
response.ret = 0;
|
||||
response.eno = 0;
|
||||
|
||||
error_invalid_fd:
|
||||
error_sock_get_fd:
|
||||
if (write(client, &response, sizeof(response)) < 0) {
|
||||
goto error_io;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
error_io:
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int server_accept_pty(patty_ax25_server *server,
|
||||
patty_ax25_call_accept_response *response,
|
||||
patty_ax25_sock *sock) {
|
||||
if ((sock->fd = open("/dev/ptmx", O_RDWR)) < 0) {
|
||||
goto error_open;
|
||||
}
|
||||
|
||||
if (grantpt(sock->fd) < 0) {
|
||||
goto error_grantpt;
|
||||
}
|
||||
|
||||
if (unlockpt(sock->fd) < 0) {
|
||||
goto error_unlockpt;
|
||||
}
|
||||
|
||||
if (ptsname_r(sock->fd, response->path, PATTY_AX25_SOCK_PATH_SIZE) < 0) {
|
||||
goto error_ptsname_r;
|
||||
}
|
||||
|
||||
response->ret = sock->fd;
|
||||
response->eno = 0;
|
||||
|
||||
return 0;
|
||||
|
||||
error_ptsname_r:
|
||||
error_unlockpt:
|
||||
error_grantpt:
|
||||
close(sock->fd);
|
||||
|
||||
error_open:
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int server_accept_unix(patty_ax25_server *server,
|
||||
patty_ax25_call_accept_response *response,
|
||||
patty_ax25_sock *sock) {
|
||||
struct sockaddr_un addr;
|
||||
|
||||
if ((sock->fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) {
|
||||
goto error_socket;
|
||||
}
|
||||
|
||||
if (snprintf(response->path, PATTY_AX25_SOCK_PATH_SIZE, "/var/run/patty/%d.sock", sock->fd) < 0) {
|
||||
goto error_snprintf;
|
||||
}
|
||||
|
||||
memset(&addr, '\0', sizeof(addr));
|
||||
addr.sun_family = AF_UNIX;
|
||||
strncpy(addr.sun_path, response->path, sizeof(addr.sun_path));
|
||||
|
||||
if (bind(sock->fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
|
||||
goto error_bind;
|
||||
}
|
||||
|
||||
response->ret = sock->fd;
|
||||
response->eno = 0;
|
||||
|
||||
return 0;
|
||||
|
||||
error_bind:
|
||||
error_snprintf:
|
||||
close(sock->fd);
|
||||
|
||||
error_socket:
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int server_accept(patty_ax25_server *server,
|
||||
int client) {
|
||||
patty_ax25_call_accept_request request;
|
||||
patty_ax25_call_accept_response response;
|
||||
|
||||
patty_ax25_sock *local,
|
||||
*remote;
|
||||
|
||||
if (read(client, &request, sizeof(request)) < 0) {
|
||||
goto error_io;
|
||||
}
|
||||
|
||||
if ((local = sock_get_fd(server, request.socket)) == NULL) {
|
||||
response.ret = -1;
|
||||
response.eno = EBADF;
|
||||
|
||||
goto error_sock_get_fd;
|
||||
}
|
||||
|
||||
if ((remote = malloc(sizeof(*remote))) == NULL) {
|
||||
goto error_malloc_remote;
|
||||
}
|
||||
|
||||
sock_init(remote, local->type);
|
||||
|
||||
if (local->type & PATTY_AX25_SOCK_PTY) {
|
||||
if (server_accept_pty(server, &response, remote) < 0) {
|
||||
goto error_server_accept_pty;
|
||||
}
|
||||
} else {
|
||||
if (server_accept_unix(server, &response, remote) < 0) {
|
||||
goto error_server_accept_unix;
|
||||
}
|
||||
}
|
||||
|
||||
error_sock_get_fd:
|
||||
if (write(client, &response, sizeof(response)) < 0) {
|
||||
goto error_io;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
error_server_accept_unix:
|
||||
error_server_accept_pty:
|
||||
free(remote);
|
||||
|
||||
error_malloc_remote:
|
||||
error_io:
|
||||
return -1;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue