Commit 9cfeb608 authored by Juliusz Chroboczek's avatar Juliusz Chroboczek

Support multiple local clients.

parent 4229bea0
......@@ -88,9 +88,6 @@ struct timeval check_neighbours_timeout;
static volatile sig_atomic_t exiting = 0, dumping = 0, reopening = 0;
int local_server_socket = -1, local_socket = -1;
int local_server_port = -1;
static int kernel_routes_callback(int changed, void *closure);
static void init_signals(void);
static void dump_tables(FILE *out);
......@@ -564,13 +561,15 @@ main(int argc, char **argv)
maxfd = MAX(maxfd, kernel_socket);
}
#ifndef NO_LOCAL_INTERFACE
if(local_socket >= 0) {
FD_SET(local_socket, &readfds);
maxfd = MAX(maxfd, local_socket);
} else if(local_server_socket >= 0) {
if(local_server_socket >= 0 &&
num_local_sockets < MAX_LOCAL_SOCKETS) {
FD_SET(local_server_socket, &readfds);
maxfd = MAX(maxfd, local_server_socket);
}
for(i = 0; i < num_local_sockets; i++) {
FD_SET(local_sockets[i], &readfds);
maxfd = MAX(maxfd, local_sockets[i]);
}
#endif
rc = select(maxfd + 1, &readfds, NULL, NULL, &tv);
if(rc < 0) {
......@@ -618,26 +617,31 @@ main(int argc, char **argv)
#ifndef NO_LOCAL_INTERFACE
if(local_server_socket >= 0 &&
FD_ISSET(local_server_socket, &readfds)) {
if(local_socket >= 0) {
close(local_socket);
local_socket = -1;
}
local_socket = accept(local_server_socket, NULL, NULL);
if(local_socket < 0) {
int s;
s = accept(local_server_socket, NULL, NULL);
if(s < 0) {
if(errno != EINTR && errno != EAGAIN)
perror("accept(local_server_socket)");
} else if(num_local_sockets >= MAX_LOCAL_SOCKETS) {
/* This should never happen, since we don't select for
the server socket in this case. But I'm paranoid. */
fprintf(stderr, "Internal error: too many local sockets.\n");
close(s);
} else {
local_notify_all();
local_sockets[num_local_sockets++] = s;
local_notify_all_1(s);
}
}
if(local_socket >= 0 && FD_ISSET(local_socket, &readfds)) {
rc = local_read(local_socket);
if(rc <= 0) {
if(rc < 0)
perror("read(local_socket)");
close(local_socket);
local_socket = -1;
for(i = 0; i < num_local_sockets; i++) {
if(FD_ISSET(local_sockets[i], &readfds)) {
rc = local_read(local_sockets[i]);
if(rc <= 0) {
if(rc < 0)
perror("read(local_socket)");
close(local_sockets[i]);
local_sockets[i] = local_sockets[--num_local_sockets];
}
}
}
#endif
......
......@@ -87,7 +87,6 @@ extern int default_wireless_hello_interval, default_wired_hello_interval;
extern int resend_delay;
extern int link_detect;
extern int all_wireless;
extern int local_socket;
extern unsigned char myid[8];
......
......@@ -41,6 +41,10 @@ int dummy;
#else
int local_server_socket = -1, local_sockets[MAX_LOCAL_SOCKETS];
int num_local_sockets = 0;
int local_server_port = -1;
int
local_read(int s)
{
......@@ -88,33 +92,30 @@ write_timeout(int fd, const void *buf, int len)
}
void
local_notify_self()
local_notify_self_1(int s)
{
char buf[512];
char host[64];
int rc;
if(local_socket < 0)
return;
rc = gethostname(host, 64);
if(rc < 0)
strncpy(host, "alamakota", 64);
rc = snprintf(buf, 512, "add self %64s id %s\n",
rc = snprintf(buf, 512, "add self %.64s id %s\n",
host, format_eui64(myid));
if(rc < 0 || rc >= 512)
goto fail;
rc = write_timeout(local_socket, buf, rc);
rc = write_timeout(s, buf, rc);
if(rc < 0)
goto fail;
return;
fail:
shutdown(local_socket, 1);
shutdown(s, 1);
return;
}
......@@ -129,14 +130,11 @@ local_kind(int kind)
}
}
void
local_notify_neighbour(struct neighbour *neigh, int kind)
static void
local_notify_neighbour_1(int s, struct neighbour *neigh, int kind)
{
char buf[512];
int rc;
if(local_socket < 0)
return;
rc = snprintf(buf, 512,
"%s neighbour %lx address %s "
......@@ -155,53 +153,63 @@ local_notify_neighbour(struct neighbour *neigh, int kind)
if(rc < 0 || rc >= 512)
goto fail;
rc = write_timeout(local_socket, buf, rc);
rc = write_timeout(s, buf, rc);
if(rc < 0)
goto fail;
return;
fail:
shutdown(local_socket, 1);
shutdown(s, 1);
return;
}
void
local_notify_xroute(struct xroute *xroute, int kind)
local_notify_neighbour(struct neighbour *neigh, int kind)
{
int i;
for(i = 0; i < num_local_sockets; i++)
local_notify_neighbour_1(local_sockets[i], neigh, kind);
}
static void
local_notify_xroute_1(int s, struct xroute *xroute, int kind)
{
char buf[512];
int rc;
if(local_socket < 0)
return;
rc = snprintf(buf, 512, "%s xroute %s prefix %s metric %d\n",
local_kind(kind),
format_prefix(xroute->prefix, xroute->plen),
format_prefix(xroute->prefix, xroute->plen),
xroute->metric);
if(rc < 0 || rc >= 512)
goto fail;
rc = write_timeout(local_socket, buf, rc);
rc = write_timeout(s, buf, rc);
if(rc < 0)
goto fail;
return;
fail:
shutdown(local_socket, 1);
shutdown(s, 1);
return;
}
void
local_notify_route(struct babel_route *route, int kind)
local_notify_xroute(struct xroute *xroute, int kind)
{
int i;
for(i = 0; i < num_local_sockets; i++)
local_notify_xroute_1(local_sockets[i], xroute, kind);
}
static void
local_notify_route_1(int s, struct babel_route *route, int kind)
{
char buf[512];
int rc;
if(local_socket < 0)
return;
rc = snprintf(buf, 512,
"%s route %s-%lx prefix %s installed %s "
"id %s metric %d refmetric %d via %s if %s\n",
......@@ -214,59 +222,64 @@ local_notify_route(struct babel_route *route, int kind)
route_metric(route), route->refmetric,
format_address(route->neigh->address),
route->neigh->ifp->name);
if(rc < 0 || rc >= 512)
goto fail;
rc = write_timeout(local_socket, buf, rc);
rc = write_timeout(s, buf, rc);
if(rc < 0)
goto fail;
return;
fail:
shutdown(local_socket, 1);
shutdown(s, 1);
return;
}
void
local_notify_route(struct babel_route *route, int kind)
{
int i;
for(i = 0; i < num_local_sockets; i++)
local_notify_route_1(local_sockets[i], route, kind);
}
static void
local_notify_xroute_callback(struct xroute *xroute, void *closure)
{
local_notify_xroute(xroute, LOCAL_ADD);
local_notify_xroute_1(*(int*)xroute, xroute, LOCAL_ADD);
}
static void
local_notify_route_callback(struct babel_route *route, void *closure)
{
local_notify_route(route, LOCAL_ADD);
local_notify_route_1(*(int*)closure, route, LOCAL_ADD);
}
void
local_notify_all()
local_notify_all_1(int s)
{
int rc;
struct neighbour *neigh;
const char *header = "BABEL 0.0\n";
if(local_socket < 0)
return;
rc = write_timeout(local_socket, header, strlen(header));
rc = write_timeout(s, header, strlen(header));
if(rc < 0)
goto fail;
local_notify_self();
local_notify_self_1(s);
FOR_ALL_NEIGHBOURS(neigh) {
local_notify_neighbour(neigh, LOCAL_ADD);
local_notify_neighbour_1(s, neigh, LOCAL_ADD);
}
for_all_xroutes(local_notify_xroute_callback, NULL);
for_all_routes(local_notify_route_callback, NULL);
rc = write_timeout(local_socket, "done\n", 5);
for_all_xroutes(local_notify_xroute_callback, &s);
for_all_routes(local_notify_route_callback, &s);
rc = write_timeout(s, "done\n", 5);
if(rc < 0)
goto fail;
return;
fail:
shutdown(local_socket, 1);
shutdown(s, 1);
return;
}
......
......@@ -30,16 +30,22 @@ struct xroute;
#ifndef NO_LOCAL_INTERFACE
#ifndef MAX_LOCAL_SOCKETS
#define MAX_LOCAL_SOCKETS 4
#endif
extern int local_server_socket, local_sockets[MAX_LOCAL_SOCKETS];
extern int num_local_sockets;
extern int local_server_port;
int local_read(int s);
void local_notify_self(void);
void local_notify_neighbour(struct neighbour *neigh, int kind);
void local_notify_xroute(struct xroute *xroute, int kind);
void local_notify_route(struct babel_route *route, int kind);
void local_notify_all(void);
void local_notify_all_1(int s);
#else
#define local_notify_self() do {} while(0)
#define local_notify_neighbour(n, k) do {} while(0)
#define local_notify_xroute(x, k) do {} while(0)
#define local_notify_route(r, k) do {} while(0)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment