Added next bunch of IBC code

This commit is contained in:
Michiel Broek 2005-04-17 10:32:41 +00:00
parent 143de27956
commit a9753fbdb0
4 changed files with 298 additions and 54 deletions

View File

@ -30,6 +30,7 @@
#include "../config.h"
#include "../lib/mbselib.h"
#include "taskstat.h"
#include "taskibc.h"
@ -38,64 +39,68 @@
int ibc_run = FALSE; /* Thread running */
extern int T_Shutdown; /* Program shutdown */
extern int internet; /* Internet status */
time_t scfg_time = (time_t)0; /* Servers config time */
ncs_list *ncsl = NULL; /* Neighbours list */
int ls; /* Listen socket */
struct sockaddr_in myaddr_in; /* Listen socket address */
typedef enum {NCS_INIT, NCS_CALL, NCS_WAITPWD, NCS_CONNECT, NCS_HANGUP, NCS_FAIL} NCSTYPE;
static char *ncsstate[] = {
(char *)"init", (char *)"call", (char *)"waitpwd", (char *)"connect", (char *)"hangup", (char *)"fail"
};
/*
* Send a UDP message to one other server.
* Add a port to the portlist
*/
void send_server(char *name, char *msg)
void fill_ncslist(ncs_list **, char *, char *);
void fill_ncslist(ncs_list **fdp, char *server, char *passwd)
{
int a1, a2, a3, a4;
int s; /* Socket */
struct hostent *he; /* Host info */
struct servent *se; /* Service information */
struct sockaddr_in server; /* Destination address */
char *errmsg;
ncs_list *tmp, *ta;
/*
* Get IP address for the hostname
*/
if (sscanf(name,"%d.%d.%d.%d",&a1,&a2,&a3,&a4) == 4)
server.sin_addr.s_addr = inet_addr(name);
else if ((he = gethostbyname(name)))
memcpy(&server.sin_addr,he->h_addr,he->h_length);
else {
switch (h_errno) {
case HOST_NOT_FOUND: errmsg = (char *)"Authoritative: Host not found"; break;
case TRY_AGAIN: errmsg = (char *)"Non-Authoritive: Host not found"; break;
case NO_RECOVERY: errmsg = (char *)"Non recoverable errors"; break;
default: errmsg = (char *)"Unknown error"; break;
tmp = (ncs_list *)malloc(sizeof(ncs_list));
memset(tmp, 0, sizeof(tmp));
tmp->next = NULL;
strncpy(tmp->server, server, 63);
strncpy(tmp->passwd, passwd, 15);
tmp->state = NCS_INIT;
tmp->action = time(NULL);
tmp->last = (time_t)0;
tmp->version = 0;
tmp->remove = FALSE;
tmp->socket = -1;
tmp->token = 0;
if (*fdp == NULL) {
*fdp = tmp;
} else {
for (ta = *fdp; ta; ta = ta->next)
if (ta->next == NULL) {
ta->next = (ncs_list *)tmp;
break;
}
Syslog('+', "No IP address for %s: %s", name, errmsg);
return;
}
}
se = getservbyname("fido", "udp");
if (se == NULL) {
Syslog('n', "Service fido udp not in /etc/services");
return;
}
server.sin_family = AF_INET;
server.sin_port = se->s_port;
Syslog('r', "Send to %s, port %d\n", inet_ntoa(server.sin_addr), ntohs(server.sin_port));
void dump_ncslist(void);
void dump_ncslist(void)
{
ncs_list *tmp;
time_t now;
s = socket(AF_INET, SOCK_DGRAM, 0);
if (s == -1) {
Syslog('r', "$Can't create socket");
return;
}
now = time(NULL);
Syslog('r', "Server State Del Next action");
Syslog('r', "--------------------------------------------------------------- ------ --- --------------");
if (bind(s, (struct sockaddr *)&server, sizeof(struct sockaddr_in)) == -1) {
Syslog('r', "$Can't bind socket");
return;
}
if (sendto(s, msg, strlen(msg), 0, (struct sockaddr *)&server, sizeof(struct sockaddr_in)) == -1) {
Syslog('r', "$Can't send message");
return;
for (tmp = ncsl; tmp; tmp = tmp->next) {
Syslog('r', "%-63s %-6s %s %d", tmp->server, ncsstate[tmp->state],
tmp->remove ? "yes":"no ", (int)tmp->action - (int)now);
}
}
@ -106,29 +111,239 @@ void send_server(char *name, char *msg)
*/
void send_all(char *msg)
{
send_server((char *)"router.mbse.ym", msg);
send_server((char *)"hppa.mbse.ym", msg);
}
void check_servers(void)
{
char *errmsg, scfgfn[PATH_MAX], buf[512];
FILE *fp;
ncs_list *tnsl;
int inlist, changed = FALSE;
time_t now;
int a1, a2, a3, a4;
struct servent *se;
struct hostent *he;
sprintf(scfgfn, "%s/etc/ibcsrv.data", getenv("MBSE_ROOT"));
/*
* Check if configuration is changed, if so then apply the changes.
*/
if (file_time(scfgfn) != scfg_time) {
Syslog('r', "%s filetime changed, rereading");
if ((fp = fopen(scfgfn, "r"))) {
fread(&ibcsrvhdr, sizeof(ibcsrvhdr), 1, fp);
while (fread(&ibcsrv, ibcsrvhdr.recsize, 1, fp)) {
Syslog('r', "IBC server \"%s\", Active %s", ibcsrv.server, ibcsrv.Active ?"Yes":"No");
if (ibcsrv.Active) {
inlist = FALSE;
for (tnsl = ncsl; tnsl; tnsl = tnsl->next) {
if (strcmp(tnsl->server, ibcsrv.server) == 0) {
inlist = TRUE;
}
}
if (!inlist ) {
Syslog('r', " not in neighbour list, add");
fill_ncslist(&ncsl, ibcsrv.server, ibcsrv.passwd);
changed = TRUE;
Syslog('+', "Added Internet BBS Chatserver %s", ibcsrv.server);
}
}
}
/*
* Now check for neighbours to delete
*/
for (tnsl = ncsl; tnsl; tnsl = tnsl->next) {
fseek(fp, ibcsrvhdr.hdrsize, SEEK_SET);
inlist = FALSE;
Syslog('r', "IBC server \"%s\"", ibcsrv.server);
while (fread(&ibcsrv, ibcsrvhdr.recsize, 1, fp)) {
if ((strcmp(tnsl->server, ibcsrv.server) == 0) && ibcsrv.Active) {
inlist = TRUE;
}
}
if (!inlist) {
Syslog('r', " not in configuration, remove");
tnsl->remove = TRUE;
tnsl->action = time(NULL);
changed = TRUE;
}
}
fclose(fp);
}
scfg_time = file_time(scfgfn);
}
if (changed)
dump_ncslist();
/*
* Check if we need to make state changes
*/
changed = FALSE;
now = time(NULL);
for (tnsl = ncsl; tnsl; tnsl = tnsl->next) {
if (((int)tnsl->action - (int)now) <= 0) {
switch (tnsl->state) {
case NCS_INIT: Syslog('r', "%s init", tnsl->server);
changed = TRUE;
/*
* If Internet is available, setup the connection.
*/
if (internet) {
/*
* Get IP address for the hostname, set default next action
* to 60 seconds.
*/
tnsl->action = now + (time_t)60;
memset(&tnsl->servaddr_in, 0, sizeof(struct sockaddr_in));
se = getservbyname("fido", "udp");
tnsl->servaddr_in.sin_family = AF_INET;
tnsl->servaddr_in.sin_port = se->s_port;
if (sscanf(tnsl->server,"%d.%d.%d.%d",&a1,&a2,&a3,&a4) == 4)
tnsl->servaddr_in.sin_addr.s_addr = inet_addr(tnsl->server);
else if ((he = gethostbyname(tnsl->server)))
memcpy(&tnsl->servaddr_in.sin_addr, he->h_addr, he->h_length);
else {
switch (h_errno) {
case HOST_NOT_FOUND: errmsg = (char *)"Authoritative: Host not found"; break;
case TRY_AGAIN: errmsg = (char *)"Non-Authoritive: Host not found"; break;
case NO_RECOVERY: errmsg = (char *)"Non recoverable errors"; break;
default: errmsg = (char *)"Unknown error"; break;
}
Syslog('+', "No IP address for %s: %s", tnsl->server, errmsg);
tnsl->state = NCS_FAIL;
break;
}
tnsl->socket = socket(AF_INET, SOCK_DGRAM, 0);
if (tnsl->socket == -1) {
Syslog('+', "$Can't create socket for %s", tnsl->server);
tnsl->state = NCS_FAIL;
break;
}
Syslog('r', "socket %d", tnsl->socket);
tnsl->token = gettoken();
tnsl->state = NCS_CALL;
tnsl->action = now + (time_t)1;
} else {
tnsl->action = now + (time_t)10;
}
break;
case NCS_CALL: Syslog('r', "%s call", tnsl->server);
sprintf(buf, "PASS %s 0000 IBC| %s\r", tnsl->passwd, tnsl->compress ? "Z":"");
if (sendto(tnsl->socket, buf, strlen(buf), 0,
(struct sockaddr *)&tnsl->servaddr_in, sizeof(struct sockaddr_in)) == -1) {
Syslog('r', "$Can't send message");
}
sprintf(buf, "SERVER seaport 0 %ld mbsebbs v%s\r", tnsl->token, VERSION);
if (sendto(tnsl->socket, buf, strlen(buf), 0,
(struct sockaddr *)&tnsl->servaddr_in, sizeof(struct sockaddr_in)) == -1) {
Syslog('r', "$Can't send message");
}
tnsl->action = now + (time_t)50;
tnsl->state = NCS_WAITPWD;
changed = TRUE;
break;
case NCS_WAITPWD: /*
* This state can be left by before the timeout is reached
* by a reply from the remote if the connection is accepted.
*/
Syslog('r', "%s waitpwd", tnsl->server);
tnsl->state = NCS_CALL;
break;
}
}
}
if (changed)
dump_ncslist();
}
/*
* IRC thread
* IBC thread
*/
void *ibc_thread(void *dummy)
{
struct servent *se;
struct pollfd pfd;
int rc, len;
socklen_t sl;
char buf[1024];
Syslog('+', "Starting IBC thread");
if ((se = getservbyname("fido", "udp")) == NULL) {
Syslog('!', "No fido udp entry in /etc/services, cannot start Internet BBS Chat");
goto exit;
}
Syslog('+', "Starting IBC thread");
myaddr_in.sin_family = AF_INET;
myaddr_in.sin_addr.s_addr = INADDR_ANY;
myaddr_in.sin_port = se->s_port;
Syslog('+', "Listen on %s, port %d\n", inet_ntoa(myaddr_in.sin_addr), ntohs(myaddr_in.sin_port));
ls = socket(AF_INET, SOCK_DGRAM, 0);
if (ls == -1) {
Syslog('!', "$Can't create socket");
goto exit;
}
if (bind(ls, (struct sockaddr *)&myaddr_in, sizeof(struct sockaddr_in)) == -1) {
Syslog('!', "$Can't bind socket");
goto exit;
}
ibc_run = TRUE;
while (! T_Shutdown) {
sleep(1);
/*
* First check Shutdown requested
*/
if (T_Shutdown) {
}
/*
* Check neighbour servers state
*/
check_servers();
/*
* Get any incoming messages
*/
pfd.fd = ls;
pfd.events = POLLIN;
pfd.revents = 0;
if ((rc = poll(&pfd, 1, 1000) < 0)) {
Syslog('r', "$poll/select failed");
} else {
Syslog('r', "poll_thread: poll interrupted rc=%d events=%04x", rc, pfd.revents);
if (pfd.revents & POLLIN || pfd.revents & POLLERR || pfd.revents & POLLHUP || pfd.revents & POLLNVAL) {
sl = sizeof(myaddr_in);
if ((len = recvfrom(ls, &buf, sizeof(buf)-1, 0,(struct sockaddr *)&myaddr_in, &sl)) != -1) {
Syslog('r', "< : \"%s\"", printable(buf, 0));
} else {
Syslog('r', "recvfrom returned len=%d", len);
}
}
}
}
exit:
@ -138,7 +353,4 @@ exit:
}
#endif

View File

@ -4,8 +4,30 @@
/* $Id$ */
#ifdef USE_EXPERIMENT
/*
* Linked list of neighbour chatservers
*/
typedef struct _ncs_list {
struct _ncs_list *next;
char server[64]; /* Server address */
char passwd[16]; /* Server password */
int state; /* Connection state */
time_t action; /* Time for next action */
time_t last; /* Last received message */
int version; /* Protocol version of peer */
unsigned remove : 1; /* If entry must be removed */
unsigned compress : 1; /* User link compression */
struct sockaddr_in servaddr_in; /* Peer socketaddress */
int socket; /* Peer socket */
unsigned long token; /* Server token */
} ncs_list;
void send_all(char *);
void *ibc_thread(void *);
#endif
#endif

View File

@ -349,6 +349,15 @@ char *getseq(void)
unsigned long gettoken(void)
{
status.sequence++;
status_write();
return status.sequence;
}
int sem_set(char *sem, int value)
{
if (!strcmp(sem, "scanout")) {

View File

@ -17,6 +17,7 @@ void stat_inc_cerr(void); /* Increase comms error */
char *stat_status(void); /* Return status record */
int stat_bbs_stat(void); /* Get BBS open status */
char *getseq(void); /* Get next sequence number */
unsigned long gettoken(void); /* Get next sequence number */
int get_zmh(void); /* Check Zone Mail Hour */
int sem_set(char *, int); /* Set/Reset semafore */
char *sem_status(char *); /* Get semafore status */