Added next bunch of IBC code
This commit is contained in:
parent
143de27956
commit
a9753fbdb0
316
mbtask/taskibc.c
316
mbtask/taskibc.c
@ -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
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
@ -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")) {
|
||||
|
@ -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 */
|
||||
|
Reference in New Issue
Block a user