/* Copyright (c) 1993 Stephen F. White */
#include "cool.h"
#include "string.h"
#include "netio.h"
#include "buf.h"
#include "netio_private.h"
#include "servers_private.h"
#include "servers.h"
static Server *promiscuous_connect (struct sockaddr_in *from,
const char *name);
static int send_to_server (Server * s, const char *buf)
{
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons (s->port);
addr.sin_addr.s_addr = htonl (s->addr);
if (sendto (yo_sock, buf, strlen (buf), 0, (struct sockaddr *) &addr,
sizeof (addr)) < 0) {
return -1;
} else {
return 0;
}
}
void connect_to_servers (void)
{
char buf[128];
Server *s;
s = serv_id2server (0);
sprintf (buf, "*connect %s\n", s->name);
for (s = servers; s; s = s->next) {
if (s->id == 0) { /* skip local server */
continue;
}
if (send_to_server (s, buf)) {
writelog ();
fprintf (stderr, "Couldn't send connect msg to server ");
perror (s->name);
}
}
}
void disconnect_from_servers (void)
{
char buf[128];
Server *s;
s = serv_id2server (0);
sprintf (buf, "*disconnect %s\n", s->name);
for (s = servers; s; s = s->next) {
if (!s->id) { /* skip local server */
continue;
}
if (s->id && s->connected) {
if (send_to_server (s, buf)) {
writelog ();
fprintf (stderr, "Couldn't send disconnect msg to server ");
perror (s->name);
}
}
}
}
int yo (Serverid server, const char *msg)
{
Server *s;
if (!(s = serv_id2server (server))) {
return -1;
} else if (!s->connected) {
return -2;
} else {
if (send_to_server (s, msg)) {
return -3;
} else {
return 0;
}
}
}
Server *promiscuous_connect (struct sockaddr_in * from, const char *name)
{
Server *s = 0;
if (promiscuous) {
s = serv_add (from, name);
if (!s) {
writelog ();
fprintf (stderr, "INVALID SERVER %s(%d), ignored\n",
addr_htoa (ntohl (from->sin_addr.s_addr)), ntohs (from->sin_port));
}
} else {
writelog ();
fprintf (stderr, "UNKNOWN SERVER %s(%d), refused\n",
addr_htoa (ntohl (from->sin_addr.s_addr)), htons (from->sin_port));
}
return s;
}
static void meta_command (struct sockaddr_in *from, char *command)
{
Server *s = 0;
char *cmd, *name, *dummy;
parse_connect (command, &cmd, &name, &dummy);
s = serv_name2server (name);
if (!strcmp (cmd + 1, "connect")) {
char buf[128];
Server *local;
if (!s) {
s = promiscuous_connect (from, name);
if (!s) {
return;
}
} else if (verify_servers && !verify_server (s, from)) {
return;
}
s->connected = 1;
s->last_msgid = -1;
writelog ();
fprintf (stderr, "Server %s (%s %d) connected\n", s->name, s->hostname,
s->port);
local = serv_id2server (0);
sprintf (buf, "*connectok %s\n", local->name);
sendto (yo_sock, buf, strlen (buf), 0, (struct sockaddr *) from,
sizeof (*from));
connect_server (s->id);
} else if (!strcmp (cmd + 1, "connectok")) {
if (!s) {
s = promiscuous_connect (from, name);
if (!s) {
return;
}
} else if (verify_servers && !verify_server (s, from)) {
return;
}
s->connected = 1;
s->last_msgid = -1;
writelog ();
fprintf (stderr, "Server %s (%s %d) connected ok\n", s->name,
s->hostname, s->port);
connect_server (s->id);
} else if (!strcmp (cmd + 1, "disconnect")) {
if (!s) {
return;
}
s->connected = 0;
writelog ();
fprintf (stderr, "Server %s (%s %d) disconnected\n", s->name,
s->hostname, s->port);
disconnect_server (s->id);
} else {
if (!s) {
return;
}
writelog ();
fprintf (stderr, "Unknown metacommand \"%s\" from server %s\n",
command, s->name);
}
}
void server_command (struct sockaddr_in *from, char *cmd)
{
Server *s;
if (cmd[0] == '*') {
meta_command (from, cmd);
} else {
s = serv_addr2server (from);
/* quietly ignore messages from unconnected servers */
if (s && s->connected) {
receive_message (s->id, cmd);
}
}
}