home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The CDPD Public Domain Collection for CDTV 4
/
CDPD_IV.bin
/
networking
/
uucp
/
amigauucpsrc
/
bms
/
register.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-06-29
|
9KB
|
357 lines
/*
* REGISTER.C
*/
#include "defs.h"
Prototype void RegisterBMS(char *, char *, char *);
Prototype void InitRegister(void);
Prototype void SMRxNoChannel(DBHan *, record_t);
Prototype void SMRxRegister(DBHan *, record_t, RegNode *, CtlNode *);
Prototype void SMTxRegister(DBHan *, record_t, RegNode *, CtlNode *);
Prototype void SMToRegister(DBHan *, record_t, RegNode *, CtlNode *);
void
InitRegister(void)
{
SetStateMachine(SMACH_REGISTRATION, SMRxRegister, SMTxRegister, SMToRegister);
}
/*
*
* Register a destination
*
* - Create a new registration node
* - Initiate a communications (allocate local id)
* - Remote id remains 0 until remote replies
*/
void
RegisterBMS(dest, retPath, alias)
char *dest;
char *retPath;
char *alias;
{
RegNode *rn;
if (rn = FindRegNode(dest, 0)) {
bmslog("Register", "Destination %s already registered", dest);
return;
}
if (retPath == NULL) {
bmslog("Register", "Need a return PATH, also suggest an ALIAS");
return;
}
rn = AllocRegNode();
if (dest)
rn->rn_Node.ln_Name = zstrdup(dest);
if (alias)
rn->rn_Alias = zstrdup(alias);
if (retPath)
rn->rn_RetPath = zstrdup(retPath);
InitCommLocalSide(SMACH_REGISTRATION, rn, &rn->rn_Comm);
SetCommMessage(&rn->rn_Comm, "REG-SEND");
}
/************************************************************************
* *
* REGISTRATION STATE MACHINE *
* *
************************************************************************
*
*
*
*/
/*
* Receive a registration or registration dequeue
* (Commands received without a channel designation)
*/
void
SMRxNoChannel(db, rid)
DBHan *db;
record_t rid;
{
long type;
long size;
RegNode *rn;
char *retPath = NULL;
char *fwdPath = NULL;
char *ptr;
char *msg = NULL;
long did = 0;
short deQ = 0;
for (rid = ScanSubRecord(db, rid, &size, &type); rid; rid = ScanNextRecord(db, rid, &size, &type)) {
switch(type) {
case DBTYPE_BMS_DEQUEUE:
deQ = 1;
if (msg)
zfree(msg);
msg = LoadRecord(db, rid, NULL, size + 1);
break;
case DBTYPE_BMS_LOID:
if (ptr = LoadRecord(db, rid, NULL, size + 1)) {
did = strtol(ptr, NULL, 0);
zfree(ptr);
}
break;
case DBTYPE_BMS_RETPATH:
if (retPath)
zfree(retPath);
retPath = LoadRecord(db, rid, NULL, size + 1);
break;
case DBTYPE_BMS_FWDPATH:
if (fwdPath)
zfree(fwdPath);
fwdPath = LoadRecord(db, rid, NULL, size + 1);
break;
default:
break;
}
}
/*
* Check deQ of registration in progress (allows us to dequeue
* registrations which have yet to get their first ack)
*/
if (deQ) {
if (retPath) {
bmslog("RxNoChannel", "Dequeue - no return path");
return;
}
if (rn = FindRegNode(retPath, 0)) {
EnterDequeueState(rn, NULL, &rn->rn_Comm, msg, 0);
} else {
bmslog("RxNoChannel", "Dequeue - node already dequeued: %s", rn->rn_Node.ln_Name);
}
return;
}
/*
* Ignore incomplete registration requests
*/
if (retPath == NULL || did == 0) {
bmslog("RxRegister", "Incomplete Registration Received: 0x%08lx '%s'",
did,
(retPath ? retPath : "<null>")
);
return;
}
/*
* Check existance of registration. Received retPath is our
* destination. Return an ack even for duplicates. If the
* DID does not match silently assign the new one (other side
* may have gotten it's database cleared)
*
* Also have fwdPath (path from him to me) now. This is required
* when one end looses a registration. NOTE THAT THE ORIGINAL
* BMS RELEASE DID NOT SEND THE DBTYPE_BMS_FWDPATH OBJECT! So
* we have to handle that case too.
*/
if (rn = FindRegNode(retPath, 1)) {
bmslog("RxRegister", "Duplicate Registration Received (ok)");
if (rn->rn_Comm.com_DID != did)
rn->rn_Comm.com_DID = did;
if (rn->rn_RetPath)
zfree(rn->rn_RetPath);
rn->rn_RetPath = fwdPath;
rn->rn_Flags |= GF_MODIFIED;
zfree(retPath);
} else {
rn = AllocRegNode();
rn->rn_Node.ln_Name = retPath;
rn->rn_RetPath = fwdPath;
InitCommRemoteSide(SMACH_REGISTRATION, rn, &rn->rn_Comm, did);
SetCommMessage(&rn->rn_Comm, "REMOTE-REGISTERED");
}
rn->rn_Comm.com_Flags |= GF_MODIFIED | GF_ALERT;
rn->rn_Comm.com_State = 8; /* SEND ACK */
}
/*
* Receive command, dequeue, or acknowledge on main channel
*/
void
SMRxRegister(db, rid, rn, cn)
DBHan *db;
record_t rid;
RegNode *rn;
CtlNode *cn;
{
long type;
long size;
for (rid = ScanSubRecord(db, rid, &size, &type); rid; rid = ScanNextRecord(db, rid, &size, &type)) {
char *ptr = LoadRecord(db, rid, NULL, size + 1);
long id = strtol(ptr, NULL, 0);
switch(type) {
case DBTYPE_BMS_ACK_REGISTER: /* +local_id */
/*
* Initial ack and keepalive
*/
bmslog("RxRegister", "Received-Ack: %s", rn->rn_Node.ln_Name);
if (rn->rn_Comm.com_DID != id)
rn->rn_Comm.com_DID = id;
if (rn->rn_Comm.com_State <= 2) {
if (rn->rn_Comm.com_State < 2)
SendMailResults(rn, NULL, "REGISTRATION COMPLETED");
/*
* ack received, set timeout for keepalive transmit
*/
rn->rn_Comm.com_State = 2;
rn->rn_Comm.com_Retries = 0;
rn->rn_Comm.com_Flags |= GF_ALERT;
} else if (rn->rn_Comm.com_State == 8) {
/*
* keepalive received, restart timeout
*/
SetCommTimeout(&rn->rn_Comm, ONEMONTH * 6);
}
rn->rn_Comm.com_Flags |= GF_MODIFIED;
break;
case DBTYPE_BMS_NAK_REGISTER: /* +errmsg */
case DBTYPE_BMS_DEQUEUE: /* +errmsg */
bmslog("RxRegister", "Received-Nak/Deq: %s", rn->rn_Node.ln_Name);
EnterDequeueState(rn, NULL, &rn->rn_Comm, ptr, 0);
break;
case DBTYPE_BMS_OPEN_GET:
bmslog("RxRegister", "Received-Open-Get: %s", rn->rn_Node.ln_Name);
SMGetNoChannel(db, rid, rn, id);
break;
case DBTYPE_BMS_OPEN_PUT:
bmslog("RxRegister", "Received-Open-Put: %s", rn->rn_Node.ln_Name);
SMPutNoChannel(db, rid, rn, id);
break;
case DBTYPE_BMS_OPEN_MIRROR:
bmslog("RxRegister", "Received-Open-Mirror: %s", rn->rn_Node.ln_Name);
SMMirrorNoChannel(db, rid, rn, id);
break;
case DBTYPE_BMS_DEQUEUE_CHANNEL:
bmslog("RxRegister", "Received-Deq-Chan: %s:%d", rn->rn_Node.ln_Name, id);
{
/*
* Find channel and dequeue
*/
CtlNode *cn;
if (cn = FindCtlNode(rn, 0, id))
EnterDequeueState(rn, cn, &cn->cn_Comm, "REMOTE-DEQUEUE", 0);
}
break;
}
zfree(ptr);
}
}
/*
* State 0: Initiate a registration, set timeout for 1 week (4 retries)
* State 1: Initiate/Retry
* State 2: Received ack for registration (timeout is for keepalive)
*
*
* State 8: Received registration send ack
* (timeout dequeue)
*/
void
SMTxRegister(db, rid, rn, cn)
DBHan *db;
record_t rid;
RegNode *rn;
CtlNode *cn;
{
char buf[128];
short deQ = 0;
short req = 0;
short ack = 0;
rn->rn_Comm.com_Flags |= GF_MODIFIED;
switch(rn->rn_Comm.com_State) {
case 0: /* Initiate */
rn->rn_Comm.com_State = 1;
SetCommTimeout(&rn->rn_Comm, ONEWEEK);
SetCommMessage(&rn->rn_Comm, "REG-SENT");
req = 1;
break;
case 1: /* Initiate Retry */
if (++rn->rn_Comm.com_Retries == 4)
deQ = 1;
SetCommTimeout(&rn->rn_Comm, ONEWEEK);
SetCommMessage(&rn->rn_Comm, "REG-RETRY");
req = 1;
break;
case 2: /* Connected, keepalive (1 month) */
SetCommMessage(&rn->rn_Comm, "REG-CONNECTED");
SetCommTimeout(&rn->rn_Comm, ONEMONTH);
break;
case 3: /* Keepalive (from timeout) */
SetCommMessage(&rn->rn_Comm, "REG-CONNECTED-LONG");
SetCommTimeout(&rn->rn_Comm, ONEMONTH);
rn->rn_Comm.com_State = 2;
rn->rn_Comm.com_Flags |= GF_MODIFIED;
ack = 1;
break;
case 8: /* Received a registration, send ack */
SetCommMessage(&rn->rn_Comm, "REG-REMOTE");
SetCommTimeout(&rn->rn_Comm, ONEMONTH * 6);
ack = 1;
break;
default:
deQ = 1;
bmslog("TxRegister", "Unknown State %s : %d", rn->rn_Node.ln_Name, rn->rn_Comm.com_State);
break;
}
if (deQ) {
EnterDequeueState(rn, cn, &rn->rn_Comm, "REG-TIMEOUT-DEQUEUE", 0);
} else if (req) {
bmslog("TxRegister", "Queue req/keep-alive: %s", rn->rn_Node.ln_Name);
sprintf(buf, "0x%lx", rn->rn_Comm.com_SID);
rid = WriteRecord(db, 0, rid, DBTYPE_BMS_REGISTER, NULL, 0);
WriteRecord(db, rid, 0, DBTYPE_BMS_LOID, buf, strlen(buf));
WriteRecord(db, rid, 0, DBTYPE_BMS_RETPATH, rn->rn_RetPath, strlen(rn->rn_RetPath));
WriteRecord(db, rid, 0, DBTYPE_BMS_FWDPATH, rn->rn_Node.ln_Name, strlen(rn->rn_Node.ln_Name));
} else if (ack) {
sprintf(buf, "0x%lx", rn->rn_Comm.com_SID);
rid = WriteBMSChannelRecord(db, 0, rid, &rn->rn_Comm);
WriteRecord(db, rid, 0, DBTYPE_BMS_ACK_REGISTER, buf, strlen(buf));
}
}
void
SMToRegister(db, rid, rn, cn)
DBHan *db;
record_t rid;
RegNode *rn;
CtlNode *cn;
{
switch(rn->rn_Comm.com_State) {
case 2: /* keepalive timeout */
rn->rn_Comm.com_Flags |= GF_MODIFIED;
++rn->rn_Comm.com_State;
SMTxRegister(db, rid, rn, cn);
break;
case 8: /* timeout! dequeue */
EnterDequeueState(rn, cn, &rn->rn_Comm, "REG-TIMEOUT-DEQUEUE", 0);
break;
default:
SMTxRegister(db, rid, rn, cn);
break;
}
}