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 >
C/C++ Source or Header  |  1994-06-29  |  9KB  |  357 lines

  1.  
  2. /*
  3.  *  REGISTER.C
  4.  */
  5.  
  6. #include "defs.h"
  7.  
  8. Prototype void RegisterBMS(char *, char *, char *);
  9. Prototype void InitRegister(void);
  10. Prototype void SMRxNoChannel(DBHan *, record_t);
  11. Prototype void SMRxRegister(DBHan *, record_t, RegNode *, CtlNode *);
  12. Prototype void SMTxRegister(DBHan *, record_t, RegNode *, CtlNode *);
  13. Prototype void SMToRegister(DBHan *, record_t, RegNode *, CtlNode *);
  14.  
  15. void
  16. InitRegister(void)
  17. {
  18.     SetStateMachine(SMACH_REGISTRATION, SMRxRegister, SMTxRegister, SMToRegister);
  19. }
  20.  
  21. /*
  22.  *
  23.  *  Register a destination
  24.  *
  25.  *  - Create a new registration node
  26.  *  - Initiate a communications (allocate local id)
  27.  *  - Remote id remains 0 until remote replies
  28.  */
  29.  
  30. void
  31. RegisterBMS(dest, retPath, alias)
  32. char *dest;
  33. char *retPath;
  34. char *alias;
  35. {
  36.     RegNode *rn;
  37.  
  38.     if (rn = FindRegNode(dest, 0)) {
  39.     bmslog("Register", "Destination %s already registered", dest);
  40.     return;
  41.     }
  42.     if (retPath == NULL) {
  43.     bmslog("Register", "Need a return PATH, also suggest an ALIAS");
  44.     return;
  45.     }
  46.     rn = AllocRegNode();
  47.     if (dest)
  48.     rn->rn_Node.ln_Name = zstrdup(dest);
  49.     if (alias)
  50.     rn->rn_Alias = zstrdup(alias);
  51.     if (retPath)
  52.     rn->rn_RetPath = zstrdup(retPath);
  53.     InitCommLocalSide(SMACH_REGISTRATION, rn, &rn->rn_Comm);
  54.     SetCommMessage(&rn->rn_Comm, "REG-SEND");
  55. }
  56.  
  57.  
  58. /************************************************************************
  59.  *                                    *
  60.  *              REGISTRATION STATE MACHINE            *
  61.  *                                    *
  62.  ************************************************************************
  63.  *
  64.  *
  65.  *
  66.  */
  67.  
  68. /*
  69.  *  Receive a registration or registration dequeue
  70.  *  (Commands received without a channel designation)
  71.  */
  72.  
  73. void
  74. SMRxNoChannel(db, rid)
  75. DBHan *db;
  76. record_t rid;
  77. {
  78.     long type;
  79.     long size;
  80.     RegNode *rn;
  81.     char *retPath = NULL;
  82.     char *fwdPath = NULL;
  83.     char *ptr;
  84.     char *msg = NULL;
  85.     long did = 0;
  86.     short deQ = 0;
  87.  
  88.     for (rid = ScanSubRecord(db, rid, &size, &type); rid; rid = ScanNextRecord(db, rid, &size, &type)) {
  89.     switch(type) {
  90.     case DBTYPE_BMS_DEQUEUE:
  91.         deQ = 1;
  92.         if (msg)
  93.         zfree(msg);
  94.         msg = LoadRecord(db, rid, NULL, size + 1);
  95.         break;
  96.     case DBTYPE_BMS_LOID:
  97.         if (ptr = LoadRecord(db, rid, NULL, size + 1)) {
  98.         did = strtol(ptr, NULL, 0);
  99.         zfree(ptr);
  100.         }
  101.         break;
  102.     case DBTYPE_BMS_RETPATH:
  103.         if (retPath)
  104.         zfree(retPath);
  105.         retPath = LoadRecord(db, rid, NULL, size + 1);
  106.         break;
  107.     case DBTYPE_BMS_FWDPATH:
  108.         if (fwdPath)
  109.         zfree(fwdPath);
  110.         fwdPath = LoadRecord(db, rid, NULL, size + 1);
  111.         break;
  112.     default:
  113.         break;
  114.     }
  115.     }
  116.  
  117.     /*
  118.      *    Check deQ of registration in progress (allows us to dequeue
  119.      *    registrations which have yet to get their first ack)
  120.      */
  121.  
  122.     if (deQ) {
  123.     if (retPath) {
  124.         bmslog("RxNoChannel", "Dequeue - no return path");
  125.         return;
  126.     }
  127.     if (rn = FindRegNode(retPath, 0)) {
  128.         EnterDequeueState(rn, NULL, &rn->rn_Comm, msg, 0);
  129.     } else {
  130.         bmslog("RxNoChannel", "Dequeue - node already dequeued: %s", rn->rn_Node.ln_Name);
  131.     }
  132.     return;
  133.     }
  134.  
  135.     /*
  136.      *    Ignore incomplete registration requests
  137.      */
  138.  
  139.     if (retPath == NULL || did == 0) {
  140.     bmslog("RxRegister", "Incomplete Registration Received: 0x%08lx '%s'",
  141.         did,
  142.         (retPath ? retPath : "<null>")
  143.     );
  144.     return;
  145.     }
  146.  
  147.     /*
  148.      *    Check existance of registration.  Received retPath is our
  149.      *    destination.  Return an ack even for duplicates.  If the
  150.      *    DID does not match silently assign the new one (other side
  151.      *    may have gotten it's database cleared)
  152.      *
  153.      *    Also have fwdPath (path from him to me) now.  This is required
  154.      *    when one end looses a registration.   NOTE THAT THE ORIGINAL
  155.      *    BMS RELEASE DID NOT SEND THE DBTYPE_BMS_FWDPATH OBJECT!  So
  156.      *    we have to handle that case too.
  157.      */
  158.  
  159.     if (rn = FindRegNode(retPath, 1)) {
  160.     bmslog("RxRegister", "Duplicate Registration Received (ok)");
  161.     if (rn->rn_Comm.com_DID != did)
  162.         rn->rn_Comm.com_DID = did;
  163.     if (rn->rn_RetPath)
  164.         zfree(rn->rn_RetPath);
  165.     rn->rn_RetPath = fwdPath;
  166.     rn->rn_Flags |= GF_MODIFIED;
  167.     zfree(retPath);
  168.     } else {
  169.     rn = AllocRegNode();
  170.     rn->rn_Node.ln_Name = retPath;
  171.     rn->rn_RetPath = fwdPath;
  172.     InitCommRemoteSide(SMACH_REGISTRATION, rn, &rn->rn_Comm, did);
  173.     SetCommMessage(&rn->rn_Comm, "REMOTE-REGISTERED");
  174.     }
  175.  
  176.     rn->rn_Comm.com_Flags |= GF_MODIFIED | GF_ALERT;
  177.     rn->rn_Comm.com_State = 8;        /*    SEND ACK  */
  178. }
  179.  
  180. /*
  181.  *  Receive command, dequeue, or acknowledge on main channel
  182.  */
  183.  
  184. void
  185. SMRxRegister(db, rid, rn, cn)
  186. DBHan *db;
  187. record_t rid;
  188. RegNode *rn;
  189. CtlNode *cn;
  190. {
  191.     long type;
  192.     long size;
  193.  
  194.     for (rid = ScanSubRecord(db, rid, &size, &type); rid; rid = ScanNextRecord(db, rid, &size, &type)) {
  195.     char *ptr = LoadRecord(db, rid, NULL, size + 1);
  196.     long id = strtol(ptr, NULL, 0);
  197.  
  198.     switch(type) {
  199.     case DBTYPE_BMS_ACK_REGISTER:    /*  +local_id    */
  200.         /*
  201.          *    Initial ack and keepalive
  202.          */
  203.  
  204.         bmslog("RxRegister", "Received-Ack: %s", rn->rn_Node.ln_Name);
  205.         if (rn->rn_Comm.com_DID != id)
  206.         rn->rn_Comm.com_DID = id;
  207.         if (rn->rn_Comm.com_State <= 2) {
  208.         if (rn->rn_Comm.com_State < 2)
  209.             SendMailResults(rn, NULL, "REGISTRATION COMPLETED");
  210.         /*
  211.          *  ack received, set timeout for keepalive transmit
  212.          */
  213.         rn->rn_Comm.com_State = 2;
  214.         rn->rn_Comm.com_Retries = 0;
  215.         rn->rn_Comm.com_Flags |= GF_ALERT;
  216.         } else if (rn->rn_Comm.com_State == 8) {
  217.         /*
  218.          *  keepalive received, restart timeout
  219.          */
  220.         SetCommTimeout(&rn->rn_Comm, ONEMONTH * 6);
  221.         }
  222.         rn->rn_Comm.com_Flags |= GF_MODIFIED;
  223.         break;
  224.     case DBTYPE_BMS_NAK_REGISTER:    /*  +errmsg    */
  225.     case DBTYPE_BMS_DEQUEUE:    /*  +errmsg    */
  226.         bmslog("RxRegister", "Received-Nak/Deq: %s", rn->rn_Node.ln_Name);
  227.         EnterDequeueState(rn, NULL, &rn->rn_Comm, ptr, 0);
  228.         break;
  229.     case DBTYPE_BMS_OPEN_GET:
  230.         bmslog("RxRegister", "Received-Open-Get: %s", rn->rn_Node.ln_Name);
  231.         SMGetNoChannel(db, rid, rn, id);
  232.         break;
  233.     case DBTYPE_BMS_OPEN_PUT:
  234.         bmslog("RxRegister", "Received-Open-Put: %s", rn->rn_Node.ln_Name);
  235.         SMPutNoChannel(db, rid, rn, id);
  236.         break;
  237.     case DBTYPE_BMS_OPEN_MIRROR:
  238.         bmslog("RxRegister", "Received-Open-Mirror: %s", rn->rn_Node.ln_Name);
  239.         SMMirrorNoChannel(db, rid, rn, id);
  240.         break;
  241.     case DBTYPE_BMS_DEQUEUE_CHANNEL:
  242.         bmslog("RxRegister", "Received-Deq-Chan: %s:%d", rn->rn_Node.ln_Name, id);
  243.         {
  244.         /*
  245.          *  Find channel and dequeue
  246.          */
  247.  
  248.         CtlNode *cn;
  249.  
  250.         if (cn = FindCtlNode(rn, 0, id))
  251.             EnterDequeueState(rn, cn, &cn->cn_Comm, "REMOTE-DEQUEUE", 0);
  252.         }
  253.         break;
  254.     }
  255.     zfree(ptr);
  256.     }
  257. }
  258.  
  259. /*
  260.  *  State 0:    Initiate a registration, set timeout for 1 week (4 retries)
  261.  *  State 1:    Initiate/Retry
  262.  *  State 2:    Received ack for registration (timeout is for keepalive)
  263.  *
  264.  *
  265.  *  State 8:    Received registration send ack
  266.  *        (timeout dequeue)
  267.  */
  268.  
  269. void
  270. SMTxRegister(db, rid, rn, cn)
  271. DBHan *db;
  272. record_t rid;
  273. RegNode *rn;
  274. CtlNode *cn;
  275. {
  276.     char buf[128];
  277.     short deQ = 0;
  278.     short req = 0;
  279.     short ack = 0;
  280.  
  281.     rn->rn_Comm.com_Flags |= GF_MODIFIED;
  282.  
  283.     switch(rn->rn_Comm.com_State) {
  284.     case 0:    /*  Initiate        */
  285.     rn->rn_Comm.com_State = 1;
  286.     SetCommTimeout(&rn->rn_Comm, ONEWEEK);
  287.     SetCommMessage(&rn->rn_Comm, "REG-SENT");
  288.     req = 1;
  289.     break;
  290.     case 1:    /*  Initiate Retry  */
  291.     if (++rn->rn_Comm.com_Retries == 4)
  292.         deQ = 1;
  293.     SetCommTimeout(&rn->rn_Comm, ONEWEEK);
  294.     SetCommMessage(&rn->rn_Comm, "REG-RETRY");
  295.     req = 1;
  296.     break;
  297.     case 2:    /*  Connected, keepalive (1 month)   */
  298.     SetCommMessage(&rn->rn_Comm, "REG-CONNECTED");
  299.     SetCommTimeout(&rn->rn_Comm, ONEMONTH);
  300.     break;
  301.     case 3:    /*  Keepalive (from timeout)    */
  302.     SetCommMessage(&rn->rn_Comm, "REG-CONNECTED-LONG");
  303.     SetCommTimeout(&rn->rn_Comm, ONEMONTH);
  304.     rn->rn_Comm.com_State = 2;
  305.     rn->rn_Comm.com_Flags |= GF_MODIFIED;
  306.     ack = 1;
  307.     break;
  308.     case 8:    /*  Received a registration, send ack    */
  309.     SetCommMessage(&rn->rn_Comm, "REG-REMOTE");
  310.     SetCommTimeout(&rn->rn_Comm, ONEMONTH * 6);
  311.     ack = 1;
  312.     break;
  313.     default:
  314.     deQ = 1;
  315.     bmslog("TxRegister", "Unknown State %s : %d", rn->rn_Node.ln_Name, rn->rn_Comm.com_State);
  316.     break;
  317.     }
  318.     if (deQ) {
  319.     EnterDequeueState(rn, cn, &rn->rn_Comm, "REG-TIMEOUT-DEQUEUE", 0);
  320.     } else if (req) {
  321.     bmslog("TxRegister", "Queue req/keep-alive: %s", rn->rn_Node.ln_Name);
  322.     sprintf(buf, "0x%lx", rn->rn_Comm.com_SID);
  323.  
  324.     rid = WriteRecord(db, 0, rid, DBTYPE_BMS_REGISTER, NULL, 0);
  325.     WriteRecord(db, rid, 0, DBTYPE_BMS_LOID, buf, strlen(buf));
  326.     WriteRecord(db, rid, 0, DBTYPE_BMS_RETPATH, rn->rn_RetPath, strlen(rn->rn_RetPath));
  327.     WriteRecord(db, rid, 0, DBTYPE_BMS_FWDPATH, rn->rn_Node.ln_Name, strlen(rn->rn_Node.ln_Name));
  328.     } else if (ack) {
  329.     sprintf(buf, "0x%lx", rn->rn_Comm.com_SID);
  330.     rid = WriteBMSChannelRecord(db, 0, rid, &rn->rn_Comm);
  331.     WriteRecord(db, rid, 0, DBTYPE_BMS_ACK_REGISTER, buf, strlen(buf));
  332.     }
  333. }
  334.  
  335. void
  336. SMToRegister(db, rid, rn, cn)
  337. DBHan *db;
  338. record_t rid;
  339. RegNode *rn;
  340. CtlNode *cn;
  341. {
  342.     switch(rn->rn_Comm.com_State) {
  343.     case 2:    /*  keepalive timeout    */
  344.     rn->rn_Comm.com_Flags |= GF_MODIFIED;
  345.     ++rn->rn_Comm.com_State;
  346.     SMTxRegister(db, rid, rn, cn);
  347.     break;
  348.     case 8:    /*  timeout! dequeue    */
  349.     EnterDequeueState(rn, cn, &rn->rn_Comm, "REG-TIMEOUT-DEQUEUE", 0);
  350.     break;
  351.     default:
  352.     SMTxRegister(db, rid, rn, cn);
  353.     break;
  354.     }
  355. }
  356.  
  357.