home *** CD-ROM | disk | FTP | other *** search
/ Collection of Hack-Phreak Scene Programs / cleanhpvac.zip / cleanhpvac / TIERRA40.ZIP / ALMOND / ALCOMM / SRC / MLAYER.C < prev    next >
C/C++ Source or Header  |  1992-07-06  |  25KB  |  1,022 lines

  1. /*
  2. * mlayer.c
  3. *
  4. *
  5. * Copyright (c) 1991, 1992 by Marc W. Cygnus and Virtual Life
  6. * All Rights Reserved.
  7. *
  8. * Many thanks to the Chick Corea Elektric Band, Front 242, and Steve Vai
  9. * for producing such incredibly wonderful music.  Go check 'em out if you
  10. * haven't already.  I *love* Vai's "Erotic Nightmares", and also "I Would
  11. * Love To" (both from the _Passion and Warfare_ album).
  12. *
  13. */
  14.  
  15. #include "mlayerp.h"
  16.  
  17.  
  18. /*** MLayer library global definitions **************************************/
  19.  
  20. MtGlobalSet        _MS;
  21. int *            _MSDFTblCnt;
  22.  
  23.  
  24. void        MHandleMessage P_(( ));
  25. void        MHandleQuery P_(( ));
  26. void        MHandleDataflow P_(( ));
  27. void        MDataflowControl P_(( ));
  28. void        MDiddleDataflow P_(( ));
  29.  
  30.  
  31.  
  32. MtStatus MInitialise( iDefHiWM, iDefLoWM, pDefMRoutines, iMRCount,
  33.               pDefQRoutines, iQRCount, pDefDRoutines, iDRCount,
  34.               pDefDIRoutines, iDIRCount )
  35.   int            iDefHiWM;
  36.   int            iDefLoWM;
  37.   pMtDefaultRoutines    pDefMRoutines;
  38.   int            iMRCount;
  39.   pMtDefaultRoutines    pDefQRoutines;
  40.   int            iQRCount;
  41.   pMtDefaultRoutines    pDefDRoutines;
  42.   int            iDRCount;
  43.   pMtDefaultRoutines    pDefDIRoutines;
  44.   int            iDIRCount;
  45. {
  46.   int            iRet;
  47.   int            i;
  48.  
  49. DEBUG( DBGAll )
  50.   ALGripe( "info", "initialising ALlayer\n" );
  51. ENDDB()
  52.   if (( iRet = ALCommInitialise( AL_Notify, AL_FullNotify )) < 0 )
  53. /*DAN    ALGripe( "ALCommInitialise", "error %d\n", iRet ), exit( -1 ); */
  54. {    ALGripe( "ALCommInitialise", "error %d\n", iRet ); return MsLOSE;}
  55.  
  56.   _MS.bReplyFlag = M_False;
  57.  
  58.   TRYCALLOC( _MS.LIT.pLIs, ppMtLinkInfo, pMtLinkInfo, M_LITBLSIZ );
  59.   if ( _MS.LIT.pLIs == NULL )        return MsNOMEM;
  60.   _MS.LIT.iLICount = 0;
  61.   _MS.LIT.iCurLink = -1;
  62.  
  63.   TRYCALLOC( _MS.MRT, pMfnRoutine, MfnRoutine, M_MRTBLSIZ );
  64.   if ( _MS.MRT == NULL )    return MsNOMEM;
  65.   TRYCALLOC( _MS.QRT, pMfnRoutine, MfnRoutine, M_QRTBLSIZ );
  66.   if ( _MS.QRT == NULL )    return MsNOMEM;
  67.   TRYCALLOC( _MS.DRT, pMfnRoutine, MfnRoutine, M_DRTBLSIZ );
  68.   if ( _MS.DRT == NULL )    return MsNOMEM;
  69.   TRYCALLOC( _MS.DIRT, pMfnRoutine, MfnRoutine, M_OUTDRTBLSIZ );
  70.   if ( _MS.DIRT == NULL )    return MsNOMEM;
  71.       /* ^^^^^^^^---> divorced phone-sex persona */
  72.  
  73.   TRYCALLOC( _MS.DFTable, phMtLinkInfo *, phMtLinkInfo, M_OUTDRTBLSIZ );
  74.   if ( _MS.DFTable == NULL )        return MsNOMEM;
  75.   TRYCALLOC( _MS.DFTEntryCount, int *, int, M_OUTDRTBLSIZ );
  76.   if ( _MS.DFTEntryCount == NULL )    return MsNOMEM;
  77.   _MSDFTblCnt = _MS.DFTEntryCount;    /* for MIsDFEnabled macro; mlayer.h */
  78.  
  79.     /* install default message routines */
  80.  
  81.   for ( i = 0; i < iMRCount; i++ ) {
  82.     if ( pDefMRoutines[i].ucWhich > M_MRTBLSIZ )
  83.       ALGripe( "MInitialise", "Message routine #%d has code (%d) larger than max (%d).\n", i, pDefMRoutines[i].ucWhich, M_MRTBLSIZ );
  84.     else
  85.       _MS.MRT[ pDefMRoutines[i].ucWhich ] = pDefMRoutines[i].fnRoutine;
  86.   }
  87.  
  88.     /* install default query routines */
  89.  
  90.   for ( i = 0; i < iQRCount; i++ ) {
  91.     if ( pDefQRoutines[i].ucWhich > M_QRTBLSIZ )
  92.       ALGripe( "MInitialise", "Query routine #%d has code (%d) larger than max (%d).\n", i, pDefQRoutines[i].ucWhich, M_QRTBLSIZ );
  93.     else
  94.       _MS.QRT[ pDefQRoutines[i].ucWhich ] = pDefQRoutines[i].fnRoutine;
  95.   }
  96.  
  97.     /* install default dataflow routines */
  98.  
  99.   for ( i = 0; i < iDRCount; i++ ) {
  100.     if ( pDefDRoutines[i].ucWhich > M_DRTBLSIZ )
  101.       ALGripe( "MInitialise", "Dataflow routine #%d has code (%d) larger than max (%d).\n", i, pDefDRoutines[i].ucWhich, M_DRTBLSIZ );
  102.     else
  103.       _MS.DRT[ pDefDRoutines[i].ucWhich ] = pDefDRoutines[i].fnRoutine;
  104.   }
  105.  
  106.     /* install default dataflow initialisation routines */
  107.  
  108.   for ( i = 0; i < iDIRCount; i++ ) {
  109.     if ( pDefDIRoutines[i].ucWhich > M_OUTDRTBLSIZ )
  110.       ALGripe( "MInitialise", "Data init routine #%d has code (%d) larger than max (%d).\n", i, pDefDIRoutines[i].ucWhich, M_OUTDRTBLSIZ );
  111.     else
  112.       _MS.DIRT[ pDefDIRoutines[i].ucWhich ] = pDefDIRoutines[i].fnRoutine;
  113.   }
  114.       
  115.   if ( iDefHiWM < 1 ) {        /* make flowcontrol disabled */
  116.     _MS.iDefaultHiWM = -1;
  117.     _MS.iDefaultLoWM = -1;
  118.   } else {
  119.  
  120.     _MS.iDefaultHiWM = iDefHiWM;
  121.  
  122.     if ( iDefLoWM < 0 )
  123.       _MS.iDefaultLoWM = 0;
  124.     else if ( iDefLoWM >= iDefHiWM )
  125.       _MS.iDefaultLoWM = iDefHiWM - 1;
  126.     else
  127.       _MS.iDefaultLoWM = iDefLoWM;
  128.   }
  129.  
  130.   return MsOK;
  131.  
  132. } /* end MInitialise() */
  133.  
  134.  
  135. MtStatus MOpenPublicPort( iPort )
  136.   int        iPort;
  137. {
  138.   int            iRet;
  139.   hALtCLink        hPortal;
  140.  
  141.   if ( iPort >= 0 ) {
  142. DEBUG( DBGAll )
  143.   ALGripe( "info", "opening TCP portal\n" );
  144. ENDDB()
  145.     if ((iRet = ALOpenTCPPortal( iPort, AL_Asynch, AL_Asynch,
  146.                  (pALtOpaque)NULL, &hPortal )) < 0)
  147. /* DAN      ALGripe( "ALOpenTCPPortal", "error %d\n", iRet );  */
  148.     return MsLOSE;
  149.   } else {
  150. DEBUG( DBGAll )
  151.     ALGripe( "info", "no TCP portal created\n" );
  152. ENDDB()
  153.   }
  154.  
  155.   return MsOK;
  156.  
  157. } /* end MOpenPublicPort() */
  158.  
  159.  
  160. MtStatus MConnectTo( sHost, iPort, phLink )
  161.   char *    sHost;
  162.   int        iPort;
  163.   hMtLinkInfo *    phLink;
  164. {
  165.   pMtLinkInfo        pNewLink;
  166.   char *        sHostname;
  167.   u_long        ulAddr;
  168.   int            iRet;
  169.   hALtCLink        hCL;
  170.  
  171. DEBUG( DBGAll )
  172.   ALGripe( "info", "resolving host\n" );
  173. ENDDB()
  174.   if (( iRet = ALInterpretHostAddress( sHost, &sHostname, &ulAddr )
  175.       ) != ALsOK ) {
  176.     ALGripe( "AL call", "ALInterpretHostAddress returned %d\n", iRet );
  177.     return ALsLOSE;
  178.   }
  179.  
  180. DEBUG( DBGAll )
  181.   ALGripe( "info", "trying connect to %s\n", sHostname );
  182. ENDDB()
  183.   
  184.   if (( iRet = ALOpenTCPPathway( ulAddr, iPort, AL_Default, AL_NoData, &hCL )
  185.       ) != ALsOK )
  186.     {ALGripe( "AL open call", "open tcp pathway returned %d\n", iRet );
  187. /* DAN    exit( -1 ); */
  188.     return MsLOSE; }
  189.  
  190.   if (( iRet = MSetupNewLinkInfo( hCL, &pNewLink, phLink )) != MsOK )
  191. /* DAN     ALGripe( "MSetupNewLinkInfo", "returned %d\n", iRet ), exit( -1 );*/
  192.     {ALGripe( "MSetupNewLinkInfo", "returned %d\n", iRet ); return MsLOSE;}
  193.  
  194.   ALSetCLPrivData( hCL, (pALtOpaque)pNewLink );
  195.  
  196.   return MsOK;
  197.  
  198. } /* end MConnectTo() */
  199.  
  200.  
  201. MtStatus MSetupNewLinkInfo( hCL, ppNewLI, phNewLI )
  202.   hALtCLink    hCL;
  203.   ppMtLinkInfo    ppNewLI;
  204.   phMtLinkInfo    phNewLI;
  205. {
  206.   pMtLinkInfo        pLI;
  207.   int            iRet;
  208.  
  209.   TRYMALLOC( pLI, pMtLinkInfo, MtLinkInfo );
  210.   if ( pLI == NULL )    return MsNOMEM;
  211.  
  212.   if ( ppNewLI != NULL )
  213.     *ppNewLI = pLI;
  214.  
  215.   pLI->hLink = hCL;
  216.   pLI->iHiWM = _MS.iDefaultHiWM;
  217.   pLI->iLoWM = _MS.iDefaultLoWM;
  218.   pLI->iAckWait = M_False;
  219.   pLI->iLevel = 0;
  220.   pLI->iOutWin = -1;        /* outgoing flow control disabled */
  221.   pLI->RB.bValid = M_False;    /* no request reply buffered */
  222.  
  223.   if (( iRet = MAddLinkToTable( pLI, phNewLI )) != MsOK )
  224.     {ALGripe( "MAddLinkToTable", "returned %d\n", iRet );
  225. /* DAN      exit( -1 ); */
  226.       return MsLOSE;}
  227.  
  228.   return MsOK;
  229.  
  230. } /* end MSetupNewLinkInfo() */
  231.  
  232.  
  233. MtStatus MAddLinkToTable( pNL, pHandle )
  234.   pMtLinkInfo    pNL;
  235.   phMtLinkInfo    pHandle;
  236. {
  237.   register int        iH;
  238.  
  239.   if ( _MS.LIT.iLICount == M_LITBLSIZ )
  240.     return MsLOSE;
  241.  
  242.   for ( iH = 0; iH < M_LITBLSIZ; iH++ )
  243.     if ( _MS.LIT.pLIs[ iH ] == NULL )
  244.       break;
  245.  
  246.   if ( iH == M_LITBLSIZ ) {                /* sanity check */
  247.     ALGripe( "MAddLinkToTable", "iLICount inconsistent with table\n" );
  248.     return MsLOSE;
  249.   }
  250.  
  251.   _MS.LIT.pLIs[ iH ] = pNL;    /* put pointer into table */
  252.  
  253.   if ( pHandle != NULL )
  254.     *pHandle = iH;
  255.  
  256.   _MS.LIT.iLICount++;
  257.  
  258. DEBUG( DBGAll )
  259.   ALGripe( "info", "added LI %d to table\n", iH );
  260. ENDDB()
  261.  
  262.   return MsOK;
  263.  
  264. } /* end MAddLinkToTable() */
  265.  
  266.  
  267. MtStatus MServiceRequests( iHow )
  268.   int        iHow;
  269. {
  270.   int            iRet;
  271.   int            iALHow;
  272.   pALtRequest        pReq;
  273.   pMtLinkInfo        pLI;
  274.  
  275.   iALHow = ( iHow == M_Wait ) ? AL_Wait : AL_NoWait;
  276.  
  277.   if (( iRet = ALServiceCLinks( AL_Synch, iALHow )) != ALsOK )
  278. /* DAN    ALGripe( "ALServiceCLinks", "error %d\n", iRet ), exit( -1 ); */
  279.     {ALGripe( "ALServiceCLinks", "error %d\n", iRet ); return MsLOSE;}
  280.  
  281.   pReq = (pALtRequest)NULL;
  282.   iRet = ALDequeueRequest( &pReq );
  283.  
  284.   while ( pReq != NULL ) {
  285. DEBUG( DBGAll )
  286.     (void) ALDumpRequest( pReq );
  287. ENDDB()
  288.  
  289.     if ( pReq->Hdr.op0 == ALrPRIVATE )
  290.  
  291.       MProcessALPrivateRequest( pReq );
  292.  
  293.     else {    /* request is not a low-level private request */
  294.  
  295.       if (( iRet = ALGetCLPrivData( pReq->hCL, (pALtOpaque)&pLI )
  296.       ) == ALsOK ) {
  297.  
  298.     /* check flowcontrol information */
  299.  
  300.     if ( pLI->iHiWM >= 0 && pLI->iAckWait == M_False ) {
  301.  
  302.       pLI->iLevel--;
  303.  
  304. DEBUG( DBGAll )
  305.           ALGripe( "info", "retrieved a new packet; now LI level = (%d)\n",
  306.            pLI->iLevel );
  307. ENDDB()
  308.       if ( pLI->iLevel <= pLI->iLoWM ) {    /* is low watermk reached? */
  309.         MtSendWindow    SW;
  310.         hMtLinkInfo    hLI;
  311.  
  312.         if ( pLI->iLevel < pLI->iLoWM )        /* sanity check */
  313.           ALGripe( "MServiceRequests", "internal bug; req level dropped below low watermark\n" );
  314.  
  315.         (void) MLinkInfoToHandle( pLI, &hLI );
  316.         SW.iUpdate = htonl( pLI->iHiWM - pLI->iLoWM );
  317. DEBUG( DBGAll )
  318.           ALGripe( "info", "level is to low watermark; updating peer.\n" );
  319. ENDDB()
  320.         if (( iRet = MGenRequest( hLI, MrPRIVATE, MrtUpdateSendWin,
  321.                       (pMtOpaque)&SW, sizeof( SW ) )) != MsOK )
  322.           ALGripe( "MServiceRequests", "MGenRequest isn't happy (%d)\n",
  323.                iRet );
  324.         pLI->iLevel = pLI->iHiWM;
  325.  
  326.       } /* end if (low watermark reached) */
  327.  
  328.     } /* end if (flowcontrol active) */
  329.  
  330.       } /* end if (clink is valid) */
  331.  
  332.       switch ( pReq->Hdr.op0 ) {
  333.  
  334.       case MrPRIVATE:
  335.     MProcessMPrivateRequest( pReq, pLI );
  336.     break;
  337.  
  338.       default:
  339.     MProcessRequest( pReq, pLI );
  340.     break;
  341.  
  342.       } /* end case */
  343.  
  344.     } /* end else (process non-al-private request) */
  345.  
  346.     (void) ALDestroyRequest( pReq );
  347.     pReq = (pALtRequest)NULL;
  348.     iRet = ALDequeueRequest( &pReq );
  349.   }
  350.  
  351.   return MsOK;
  352.  
  353. } /* end MServiceRequests() */
  354.  
  355.  
  356. MtStatus MGenRequest( hLI, op0, op1, pData, iDataLen )
  357.   hMtLinkInfo    hLI;
  358.   u_char    op0;
  359.   u_char    op1;
  360.   pMtOpaque    pData;
  361.   int        iDataLen;
  362. {
  363.   int            iRet;
  364.   pMtLinkInfo        pLI;
  365.  
  366.   if ( ! MmIsLIHandleValid( hLI ) )
  367.     return MsLOSE;
  368.  
  369.   pLI = MmHandleToLinkInfo( hLI );
  370.  
  371.       /* if outgoing flow control is disabled, iOutWin will be -1 */
  372.  
  373.   while ( pLI->iOutWin == 0 ) {    /* if window is zero (and thus outgoing */
  374.                     /*   f/c is enabled), wait for it to open */
  375.  
  376. DEBUG( DBGAll )
  377.     ALGripe( "info", "outgoing send window is closed for LI (%d). waiting...\n", hLI );
  378. ENDDB()
  379.  
  380.     if (( iRet = MServiceRequests( M_Wait )) != MsOK ) {
  381.       ALGripe( "MGenRequest", "MServiceRequests failed while waiting for send window\n" );
  382.       return MsLOSE;
  383.     }
  384.  
  385.     /* at this point we must verify that LI handle references a valid */
  386.     /*   LI structure, ie: that the link didn't die on us during the */
  387.     /*   MServiceRequests wait. */
  388.  
  389.   if (( pLI = MmHandleToLinkInfo( hLI )) == NULL )
  390.     return MsDEADLINK;        /* yep, link died on us.  inform caller */
  391.  
  392. DEBUG( DBGAll )
  393.     if ( pLI->iOutWin == -1 )
  394.       ALGripe( "info", "hello, outgoing f/c has just been disabled\n" );
  395.     else if ( pLI->iOutWin > 0 )
  396.       ALGripe( "info", "okay, outgoing send window has jumped to (%d)\n",
  397.            pLI->iOutWin );
  398. ENDDB()
  399.  
  400.   } /* end while (f/c enabled & window closed) */
  401.  
  402.   if ( pLI->iOutWin > 0 )    /* if f/c is not disabled, */
  403.     pLI->iOutWin--;        /*   record the transmission of this packet */
  404.  
  405. DEBUG( DBGAll )
  406.   ALGripe( "info", "...outgoing packet sent; now outwin == %d\n",
  407.        pLI->iOutWin );
  408. ENDDB()
  409.   if (( iRet = ALTCPGenRequest( pLI->hLink, op0, op1, (pALtOpaque)pData,
  410.                     iDataLen )) != ALsOK ) {
  411.  
  412.     if ( iRet == ALsDEAD )
  413.       return MsDEADLINK;    /* inform caller */
  414.     else if ( iRet != ALsLOSE )
  415. /* DAN      ALGripe( "ALTCPGenRequest", "error %d\n", iRet ), exit( -1 );*/
  416.       {ALGripe( "ALTCPGenRequest", "error %d\n", iRet ); return MsLOSE;}
  417.  
  418.   }
  419.  
  420.   return MsOK;
  421.  
  422. } /* end MGenRequest */
  423.  
  424.  
  425. MtStatus MGenRequestWithReply( hLI, op0, op1, pData, iDataLen, ppReplyData,
  426.                    piReplyDataLen )
  427.   hMtLinkInfo    hLI;
  428.   u_char    op0;
  429.   u_char    op1;
  430.   pMtOpaque    pData;
  431.   int        iDataLen;
  432.   pMtOpaque *    ppReplyData;
  433.   int *        piReplyDataLen;
  434. {
  435.   int            iRet;
  436.   pMtLinkInfo        pLI;
  437.   pALtRequest        pReq;
  438.   
  439.   if (( iRet = MGenRequest( hLI, op0, op1, pData, iDataLen ) ) != MsOK )
  440.     return iRet;
  441.  
  442.   pLI = MmHandleToLinkInfo( hLI );
  443.  
  444.   pLI->RB.bValid = M_False;    /* mark this LI's reply buffer invalid */
  445.  
  446. DEBUG( DBGAll )
  447.   ALGripe( "info", "just made a query; waiting for reply...\n" );
  448. ENDDB()
  449.  
  450.   while ( pLI->RB.bValid == M_False ) {
  451.  
  452.     if (( iRet = MServiceRequests( M_Wait )) != MsOK ) {
  453.       ALGripe( "MGenRequestWithReply", "MServiceRequests failed (%d)\n",
  454.            iRet );
  455.       return MsLOSE;
  456.     }
  457. DEBUG( DBGAll )
  458.     ALGripe( "info", "(inside reply waiting loop)\n" );
  459. ENDDB()
  460.  
  461.       /* at this point we must verify that LI handle references a valid */
  462.     /*   LI structure, ie: that the link didn't die on us during the */
  463.     /*   MServiceRequests wait.  Same check is done during a closed */
  464.     /*   output flow window inside of MGenRequest(). */
  465.  
  466.     if (( pLI = MmHandleToLinkInfo( hLI )) == NULL ) {
  467.       *ppReplyData = (pMtOpaque)NULL;    /* help idiot-proof this function */
  468.       *piReplyDataLen = 0;
  469.       return MsDEADLINK;    /* yep, link died on us.  inform caller */
  470.     }
  471.  
  472.   } /* end while (reply not gotten) */
  473.  
  474.   *ppReplyData = pLI->RB.pData;
  475.   *piReplyDataLen = pLI->RB.iDataLen;
  476.  
  477. DEBUG( DBGAll )
  478.   ALGripe( "info", "got the desired reply.\n" );
  479. ENDDB()
  480.  
  481.   return MsOK;
  482.  
  483. } /* end MGenRequestWithReply() */
  484.  
  485.  
  486. void MProcessALPrivateRequest( pReq )
  487.   pALtRequest    pReq;
  488. {
  489.   pMtLinkInfo        pLI;
  490.   MtStatus        iRet;
  491.  
  492.   switch ( pReq->Hdr.op1 ) {
  493.  
  494.   case ALrDeadCLink:
  495.     MCleanupDeadLink( (pALtCLDeathInfo)pReq->pData );
  496.     break;
  497.  
  498.   case ALrNewCLink:
  499.     if (( iRet = MSetupNewLinkInfo( pReq->hCL, &pLI, (phMtLinkInfo)NULL )
  500.     ) != MsOK )
  501.       ALGripe( "MProcALPrivReq.", "MSetupNewLinkInfo failed (%d)\n", iRet );
  502.     ALSetCLPrivData( pReq->hCL, (pALtOpaque)pLI );
  503.     break;
  504.  
  505.   default:
  506.     ALGripe( "MProcessALPrivateRequest", "unknown AL request %d\n",
  507.          pReq->Hdr.op1 );
  508.     break;
  509.  
  510.   }
  511.  
  512. } /* end MProcessALPrivateRequest() */
  513.  
  514.  
  515. void MProcessMPrivateRequest( pReq, pLI )
  516.   pALtRequest    pReq;
  517.   pMtLinkInfo    pLI;
  518. {
  519.   pMtSendWindow        pSW;
  520.   hMtLinkInfo        hLI;
  521.   MtStatus        iRet;
  522.  
  523.   switch ( pReq->Hdr.op1 ) {
  524.  
  525.   case MrtSetSendWin:
  526.     pSW = (pMtSendWindow)pReq->pData;
  527.     pSW->iUpdate = ntohl( pSW->iUpdate );
  528.     pLI->iOutWin = pSW->iUpdate;
  529.     (void) MLinkInfoToHandle( pLI, &hLI );
  530.     if ( pSW->iUpdate != -1 ) {
  531.       if (( iRet = MGenRequest( hLI, MrPRIVATE, MrtAckSetSendWin, M_NoData, 0 )
  532.       ) != MsOK )
  533.     ALGripe( "MProcMPrivReq.", "MGenRequest isn't happy (%d)\n", iRet );
  534.     }
  535. DEBUG( DBGAll )
  536.     ALGripe( "info", "remote set our send window to (%d)\n", pSW->iUpdate );
  537.     if ( pSW->iUpdate > -1 )
  538.       ALGripe( "info", "...sent an acknowledgement\n" );
  539. ENDDB()
  540.     break;
  541.  
  542.   case MrtAckSetSendWin:
  543.     if ( pLI->iAckWait != M_True )    /* sanity check */
  544.       ALGripe( "MProcMPrivReq.", "iAckWait isn't set to true; hmm...\n" );
  545.     pLI->iAckWait = M_False;    /* reset the wait state */
  546. DEBUG( DBGAll )
  547.     ALGripe( "info", "got ack of send-window setting\n" );
  548. ENDDB()
  549.     break;
  550.  
  551.   case MrtUpdateSendWin:
  552.     pSW = (pMtSendWindow)pReq->pData;
  553.     pSW->iUpdate = ntohl( pSW->iUpdate );
  554.     pLI->iOutWin += pSW->iUpdate;
  555. DEBUG( DBGAll )
  556.     ALGripe( "info", "send win just updated by (%d) to total of (%d)\n",
  557.          pSW->iUpdate, pLI->iOutWin );
  558. ENDDB()
  559.     break;
  560.     
  561.   default:
  562.     ALGripe( "MProcessMPrivateRequest", "unknown M request %d\n",
  563.          pReq->Hdr.op1 );
  564.     break;
  565.  
  566.   }
  567.  
  568. } /* end MProcessMPrivateRequest() */
  569.  
  570.  
  571. void MProcessRequest( pReq, pLI )
  572.   pALtRequest    pReq;
  573.   pMtLinkInfo    pLI;
  574. {
  575.  
  576.   switch ( pReq->Hdr.op0 ) {
  577.  
  578.   case MrMessage:
  579.     MHandleMessage( pReq, pLI );
  580.     break;
  581.  
  582.   case MrQuery:
  583.     MHandleQuery( pReq, pLI );
  584.     break;
  585.  
  586.   case MrQueryReply:
  587.     pLI->RB.ucOp = pReq->Hdr.op1;
  588.     pLI->RB.pData = pReq->pData;
  589.     pLI->RB.iDataLen = pReq->Hdr.len << 2;
  590.     pLI->RB.bValid = M_True;
  591.     break;
  592.  
  593.   case MrQueryError:
  594.     pLI->RB.ucOp = pReq->Hdr.op1;
  595.     pLI->RB.pData = (pMtOpaque)NULL;
  596.     pLI->RB.iDataLen = 0;
  597.     pLI->RB.bValid = M_True;
  598.     break;
  599.  
  600.   case MrModifyDataflow:
  601.     MDataflowControl( pReq, pLI );
  602.     break;
  603.  
  604.   case MrDataflowEvent:
  605.     MHandleDataflow( pReq, pLI );
  606.     break;
  607.  
  608.   default:
  609.     ALGripe( "MProcessRequest", "unknown M request, op0 = %d\n",
  610.          pReq->Hdr.op0 );
  611.     break;
  612.  
  613.   }
  614.  
  615. } /* end MProcessRequest() */
  616.  
  617.  
  618. void MHandleMessage( pReq, pLI )
  619.   pALtRequest    pReq;
  620.   pMtLinkInfo    pLI;
  621. {
  622.   register u_char    ucM;
  623.   hMtLinkInfo        hLI;
  624.  
  625.   ucM = pReq->Hdr.op1;
  626. DEBUG( DBGAll )
  627.   ALGripe( "info", "handling message (%d)\n", ucM );
  628. ENDDB()
  629.  
  630.   (void) MLinkInfoToHandle( pLI, &hLI );
  631.  
  632.   if ( ucM > M_MRTBLSIZ )
  633.     ALGripe( "MHandleMessage", "message (%d) outside max (%d)\n", ucM,
  634.          M_MRTBLSIZ );
  635.   else if ( _MS.MRT[ ucM ] == NULL )
  636.     ALGripe( "MHandleMessage", "no message routine registered for (%d)\n",
  637.          ucM );
  638.   else
  639.     ( _MS.MRT[ ucM ] )( ucM, pReq->pData, hLI );
  640.  
  641. } /* end MHandleMessage() */
  642.  
  643.  
  644. void MHandleQuery( pReq, pLI )
  645.   pALtRequest    pReq;
  646.   pMtLinkInfo    pLI;
  647. {
  648.   register u_char    ucQ;
  649.   hMtLinkInfo        hLI;
  650.  
  651.   ucQ = pReq->Hdr.op1;
  652. DEBUG( DBGAll )
  653.   ALGripe( "info", "handling query (%d)\n", ucQ );
  654. ENDDB()
  655.  
  656.   (void) MLinkInfoToHandle( pLI, &hLI );
  657.  
  658.   if ( ucQ > M_QRTBLSIZ )
  659.     ALGripe( "MHandleQuery", "query (%d) outside max (%d)\n", ucQ,
  660.          M_QRTBLSIZ );
  661.   else if ( _MS.QRT[ ucQ ] == NULL ) {
  662.     ALGripe( "MHandleQuery", "no query routine registered for (%d)\n", ucQ );
  663.     (void) ALTCPGenRequest( pLI->hLink, MrQueryError, ucQ, (pMtOpaque)NULL,
  664.                 0 );
  665.   } else {
  666.  
  667.     _MS.bReplyFlag = M_True;    /* set reply verification flag */
  668.  
  669.         /* call registered query handler routine */
  670.  
  671.     ( _MS.QRT[ ucQ ] )( ucQ, pReq->pData, hLI );
  672.  
  673.     if ( _MS.bReplyFlag == M_True ) {
  674.       _MS.bReplyFlag = M_False;
  675.       (void) ALTCPGenRequest( pLI->hLink, MrQueryError, ucQ, (pMtOpaque)NULL,
  676.                  0 );
  677.     }
  678.  
  679.   }
  680.  
  681. } /* end MHandleQuery() */
  682.  
  683.  
  684. MtStatus MGenReply( hLI, ucOutOp, pData, iDataLen )
  685.   hMtLinkInfo    hLI;
  686.   u_char    ucOutOp;
  687.   pMtOpaque    pData;
  688.   int        iDataLen;
  689. {
  690.   int            iRet;
  691.  
  692.   if ( ! MmIsLIHandleValid( hLI ) )
  693.     return MsLOSE;
  694.  
  695.   iRet = MGenRequest( hLI, MrQueryReply, ucOutOp, pData, iDataLen );
  696.  
  697.   _MS.bReplyFlag = M_False;
  698.  
  699.   return iRet;
  700.  
  701. } /* end MGenReply() */
  702.  
  703.  
  704. void MHandleDataflow( pReq, pLI )
  705.   pALtRequest    pReq;
  706.   pMtLinkInfo    pLI;
  707. {
  708.   register u_char    ucDF;
  709.   hMtLinkInfo        hLI;
  710.  
  711.   (void) MLinkInfoToHandle( pLI, &hLI );
  712.   ucDF = pReq->Hdr.op1;
  713.   if ( ucDF > M_DRTBLSIZ )
  714.     ALGripe( "MHandleDataflow", "dataflow type (%d) outside max (%d)\n", ucDF,
  715.          M_DRTBLSIZ );
  716.   else if ( _MS.DRT[ ucDF ] == NULL )
  717.     ALGripe( "MHandleDataflow", "no handler installed for type (%d)\n", ucDF );
  718.   else
  719.     ( _MS.DRT[ ucDF ] )( ucDF, pReq->pData, hLI );
  720.  
  721. } /* end MHandleDataflow() */
  722.  
  723.  
  724. void MDataflowControl( pReq, pLI )
  725.   pALtRequest    pReq;
  726.   pMtLinkInfo    pLI;
  727. {
  728.   register u_char    ucDF;
  729.   register int        iOperation;
  730.   int            hLI;
  731.  
  732. DEBUG( DBGAll )
  733.   ALGripe( "info", "changing dataflow...\n" );
  734. ENDDB()
  735.  
  736.   (void) MLinkInfoToHandle( pLI, &hLI );
  737.  
  738.   if ( pReq->pData == NULL ) {
  739.     ALGripe( "MDataflowControl", "no dataflow operation specified\n" );
  740.     return;
  741.   }
  742.  
  743.   iOperation = ntohl( *( (int *)pReq->pData ) );
  744.  
  745.   ucDF = pReq->Hdr.op1;
  746.  
  747.   MDiddleDataflow( ucDF, hLI, iOperation );
  748.  
  749. } /* end MDataflowControl() */
  750.  
  751.  
  752. void MDiddleDataflow( ucDF, hLI, iHow )
  753.   u_char    ucDF;
  754.   int        iHow;
  755. {
  756.   int            iTgt;
  757.   int            iEnd;
  758.   phMtLinkInfo        pLIEntry;
  759.   register int        i;
  760.  
  761.   if ( ucDF > M_OUTDRTBLSIZ ) {
  762.     ALGripe( "MDiddleDataflow", "specified dataflow type (%d) is outside max (%d)\n", ucDF, M_OUTDRTBLSIZ );
  763.     return;
  764.   }
  765.  
  766.   if ( iHow == M_Enable ) {    /* enable a dataflow... */
  767.  
  768.     /* if slot is null, allocate initial entries */
  769.     
  770.     if ( ( pLIEntry = _MS.DFTable[ ucDF ] ) == NULL ) {
  771. DEBUG( DBGAll )
  772.       ALGripe( "info", "no slot in table for (%d); creating...\n", ucDF );
  773. ENDDB()
  774.  
  775.       TRYMALLOCBLK( pLIEntry, phMtLinkInfo, hMtLinkInfo,
  776.             M_DFBLKSIZ );
  777.       if ( pLIEntry == NULL ) {
  778.     ALGripe( "MDiddleDataflow", "no memory for new LI table block\n" );
  779.     return;
  780.       }
  781.       _MS.DFTEntryCount[ ucDF ] = M_DFBLKSIZ;
  782.       for ( i = 0; i < M_DFBLKSIZ; i++ )
  783.     pLIEntry[ i ] = -1;
  784.       _MS.DFTable[ ucDF ] = pLIEntry;
  785.       iTgt = 0;
  786.  
  787.     } else {    /* slot not null; locate empty spot & check to see if LI is */
  788.         /*   possibly already in the table */      
  789.  
  790.       for ( iTgt = 0; iTgt < _MS.DFTEntryCount[ ucDF ]; iTgt++ )
  791.         if ( pLIEntry[ iTgt ] == hLI )    /* handle already req'd df */
  792.       return;
  793.     else if ( pLIEntry[ iTgt ] == -1 )    /* found vacant spot */
  794.       break;
  795.  
  796.       if ( iTgt == _MS.DFTEntryCount[ ucDF ] ) { /* need 2 make slot bigger */
  797.  
  798.     TRYREALLOCBLK( pLIEntry, pLIEntry, phMtLinkInfo, hMtLinkInfo,
  799.                iTgt + M_DFBLKSIZ );
  800.     for ( i = iTgt; i < iTgt + M_DFBLKSIZ; i++ )
  801.       pLIEntry[ i ] = -1;
  802.     _MS.DFTEntryCount += M_DFBLKSIZ;
  803.     _MS.DFTable[ ucDF ] = pLIEntry;    /* in case it's changed */
  804.  
  805.       }    /* end make slot bigger */
  806.  
  807.     } /* end locating blank entry */
  808.  
  809.     pLIEntry[ iTgt ] = hLI;    /* put LI in table */
  810.  
  811.     /* NOTICE: I'm not going to put in code to deal with the MtDFSets */
  812.     /*   right now.  They may be superfluous with the addition of the */
  813.     /*   DFTable.  If that's the case, then they'll disappear. */
  814.  
  815.         /* see if there's a df init procedure registered; call it if so */
  816.  
  817.     if ( _MS.DIRT[ ucDF ] != NULL )
  818.       (_MS.DIRT[ ucDF ])( ucDF, hLI );
  819.  
  820.   } else if ( iHow == M_Disable ) {        /* disable a dataflow... */
  821.  
  822.     /* if slot is null, ignore disable request */
  823.  
  824.     if ( ( pLIEntry = _MS.DFTable[ ucDF ] ) == NULL )
  825.       return;
  826.  
  827.         /* look for handle in slot; remove if there, ignore if not */
  828.  
  829.     for ( iTgt = 0; iTgt < _MS.DFTEntryCount[ ucDF ]; iTgt++ )
  830.       if ( pLIEntry[ iTgt ] == hLI )
  831.     break;
  832.  
  833.     for ( iEnd = _MS.DFTEntryCount[ ucDF ] - 1; iEnd > iTgt; iEnd-- )
  834.       if ( pLIEntry[ iEnd ] != -1 )
  835.     break;
  836.  
  837.     if ( iTgt != iEnd )
  838.       pLIEntry[ iTgt ] = pLIEntry[ iEnd ];
  839.  
  840.     if ( iEnd > 0 )
  841.       pLIEntry[ iEnd ] = -1;
  842.     else {
  843.       (void) ALFree( (char *)pLIEntry );
  844.       _MS.DFTable[ ucDF ] = (phMtLinkInfo)NULL;
  845.       _MS.DFTEntryCount[ ucDF ] = 0;
  846.     }
  847.  
  848.   } else
  849.     ALGripe( "MDiddleDataflow", "unknown operation(%d)\n", iHow );
  850.  
  851. } /* end MDiddleDataflow() */
  852.  
  853.  
  854. void MCleanupDeadLink( pDI )
  855.   pALtCLDeathInfo    pDI;
  856. {
  857.   pMtLinkInfo        pLI;
  858.   hMtLinkInfo        hLI;
  859.   register int        i;
  860.  
  861.   pLI = (pMtLinkInfo)pDI->pData;
  862.  
  863.   (void) MLinkInfoToHandle( pLI, &hLI );
  864.  
  865.   for ( i = 0; i < M_OUTDRTBLSIZ; i++ )
  866.     MDiddleDataflow( i, hLI, M_Disable );
  867.  
  868. DEBUG( DBGAll )
  869.     ALGripe( "info", "wiped LI %d\n", hLI );
  870. ENDDB()
  871.  
  872.   ALFree( (char *)pLI );
  873.   pLI = (pMtLinkInfo)NULL;
  874.   _MS.LIT.iLICount--;
  875.   _MS.LIT.pLIs[ hLI ] = (pMtLinkInfo)NULL;
  876.  
  877. } /* end MCleanupDeadLink() */
  878.  
  879.  
  880. MtStatus MLinkInfoToHandle( pLI, phLI )
  881.   pMtLinkInfo    pLI;
  882.   phMtLinkInfo    phLI;
  883. {
  884.   register int        i;
  885.  
  886.   if ( phLI == NULL )
  887.     return MsLOSE;
  888.  
  889.   for ( i = 0; i < _MS.LIT.iLICount; i++ )
  890.     if ( _MS.LIT.pLIs[ i ] == pLI )
  891.       break;
  892.  
  893.   if ( i == M_LITBLSIZ )
  894.     return MsLOSE;
  895.  
  896.   *phLI = i;
  897.  
  898.   return MsOK;
  899.  
  900. } /* end MLinkInfoToHandle() */
  901.  
  902.  
  903. int MShowDFTable( )
  904. {
  905.   int        i;
  906.  
  907.   printf( "DFTable[0]: " );
  908.   if ( _MS.DFTable[0] == NULL )
  909.     printf( "<null>\n" );
  910.   else {
  911.     printf( "[%d] [%d] [%d] [%d]\n", _MS.DFTable[0][0], _MS.DFTable[0][1],
  912.         _MS.DFTable[0][2], _MS.DFTable[0][3] );
  913.   }
  914.  
  915. } /* end MShowDFTable() */
  916.  
  917.  
  918. MtStatus MSetFlowcontrol( hLI, iHiWM, iLoWM )
  919.   hMtLinkInfo    hLI;
  920.   int        iHiWM;
  921.   int        iLoWM;
  922. {
  923.   pMtLinkInfo        pLI;
  924.   MtSendWindow        SW;
  925.   MtStatus        iRet;
  926.  
  927.   if ( ! MmIsLIHandleValid( hLI ) )
  928.     return MsLOSE;
  929.  
  930.   pLI = MmHandleToLinkInfo( hLI );
  931.  
  932.   if ( iHiWM < 0 ) {
  933.     iHiWM = -1;        /* turn off flowcontrol; no need to wait for ack */
  934.     iLoWM = -1;
  935.   } else {
  936.  
  937.     if ( iHiWM == 0 )        /* whatever LoWM is, it has to be less than */
  938.       iHiWM = 1;        /*   iHiWM, so iHiWM can't be zero. */
  939.  
  940.     if ( iLoWM < 0 )
  941.       iLoWM = 0;
  942.     else if ( iLoWM >= iHiWM )
  943.       iLoWM = iHiWM - 1;
  944.  
  945.     pLI->iAckWait = M_True;    /* we're going to be waiting for an ack */
  946.  
  947.   }
  948.  
  949.   pLI->iHiWM = iHiWM;
  950.   pLI->iLoWM = iLoWM;
  951.   pLI->iLevel = iHiWM;
  952.     /* artificially inflate the update by one to account for peer's */
  953.       /*   transmission of an ACK, which is counted on peer's end but */
  954.       /*   not included in the definition of our iLevel peer estimate */
  955.   SW.iUpdate = ( iHiWM == -1 ) ? -1 : iHiWM + 1;
  956.  
  957. DEBUG( DBGAll )
  958.   ALGripe( "info", "requesting flow control setting; window (%d)\n",
  959.        iHiWM );
  960. ENDDB()
  961.  
  962.   if (( iRet = MGenRequest( hLI, MrPRIVATE, MrtSetSendWin, (pMtOpaque)&SW,
  963.                 sizeof( SW ) )) != MsOK )
  964.     ALGripe( "MSetFlowcontrol", "MGenRequest isn't happy: (%d)\n", iRet );
  965.  
  966.   return iRet;
  967.  
  968. } /* end MSetFlowcontrol() */
  969.  
  970.  
  971. MtStatus MDistributeDataflow( ucDF, pData, iDataLen )
  972.   u_char    ucDF;
  973.   pMtOpaque    pData;
  974.   int        iDataLen;
  975. {
  976.   register int        i;
  977.   MtStatus        iRet;
  978.   phMtLinkInfo        pLIs;
  979.  
  980.   if ( ucDF >= M_OUTDRTBLSIZ ) {
  981.     ALGripe( "MDistDF.", "df type (%d) outside max (%d)\n", ucDF,
  982.          M_OUTDRTBLSIZ );
  983.     return MsLOSE;
  984.   }
  985.  
  986.   pLIs = _MS.DFTable[ ucDF ];
  987.   for ( i = 0; i < _MS.DFTEntryCount[ ucDF ] && pLIs[ i ] != -1; i++ ) {
  988.  
  989.     if (( iRet = MGenRequest( pLIs[ i ], MrDataflowEvent, ucDF, pData,
  990.                   iDataLen )) != MsOK )
  991.       ALGripe( "MDistDF.", "note MGenRequest failure (%d) on LI (%d)\n",
  992.            iRet, pLIs[i] );
  993.  
  994.   }
  995.  
  996.   return MsOK;
  997.  
  998. } /* end MDistributeDataflow() */
  999.  
  1000.  
  1001. MtStatus MGetLinkFD( hLI, pFD )
  1002.   hMtLinkInfo    hLI;
  1003.   int *        pFD;
  1004. {
  1005.   pMtLinkInfo    pLI;
  1006.  
  1007.   if ( ! MmIsLIHandleValid( hLI ) )
  1008.     return MsLOSE;
  1009.  
  1010.   pLI = MmHandleToLinkInfo( hLI );
  1011.  
  1012.   (void) ALGetLinkFD( pLI->hLink, pFD );
  1013.  
  1014.   return MsOK;
  1015.  
  1016. }
  1017.  
  1018.  
  1019.  
  1020.  
  1021. /* end mlayer.c */
  1022.