⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dcpgpkt.c

📁 大量的汇编程序源代码
💻 C
📖 第 1 页 / 共 4 页
字号:

   do {
      if (gmachine(0) != POK)    /* Spin with no timeout             */
         return(-1);
   } while (nbuffers >= nwindows);

/*--------------------------------------------------------------------*/
/*               Place packet in table and mark unacked               */
/*--------------------------------------------------------------------*/

   MEMCPY(outbuf[sbu], data, len);

/*--------------------------------------------------------------------*/
/*                       Handle short packets.                        */
/*--------------------------------------------------------------------*/

   xmitlen[sbu] = s_pktsize;
   if (variablepacket)
      while ( ((len * 2) < (short) xmitlen[sbu]) && (xmitlen[sbu] > MINPKT) )
         xmitlen[sbu] /= 2;

   if ( xmitlen[sbu] < MINPKT )
   {
      printmsg(0,"gsendpkt: Bad packet size %d, "
               "data length %d",
               xmitlen[sbu], len);
      xmitlen[sbu] = MINPKT;
   }

   delta = xmitlen[sbu] - len;
   if (delta > 127)
   {
      MEMMOVE(outbuf[sbu] + 2, outbuf[sbu], len);
      MEMSET(outbuf[sbu]+len+2, 0, delta - 2);
                              /* Pad with nulls.  Ugh.               */
      outbuf[sbu][0] = (unsigned char) ((delta & 0x7f) | 0x80);
      outbuf[sbu][1] = (unsigned char) (delta >> 7);
   } /* if (delta > 127) */
   else if (delta > 0 )
   {
      MEMMOVE(outbuf[sbu] + 1, outbuf[sbu], len);
      outbuf[sbu][0] = (unsigned char) delta;
      MEMSET(outbuf[sbu]+len+1, 0, delta - 1);
                              /* Pad with nulls.  Ugh.               */
   } /* else if (delta > 0 )  */

/*--------------------------------------------------------------------*/
/*                            Mark packet                             */
/*--------------------------------------------------------------------*/

   outlen[sbu] = len;
   ftimer[sbu] = time(nil(long));
   nbuffers++;

/*--------------------------------------------------------------------*/
/*                              send it                               */
/*--------------------------------------------------------------------*/

   gspack(DATA, rwl, swu, outlen[sbu], xmitlen[sbu], outbuf[sbu]);

   swu = nextpkt(swu);        /* Bump send window                    */
   sbu = nextbuf( sbu );      /* Bump to next send buffer            */

#ifdef _DEBUG
   debuglevel = savedebug;
#endif

   return(0);

} /*gsendpkt*/


/*--------------------------------------------------------------------*/
/*    g e o f p k t                                                   */
/*                                                                    */
/*    Transmit EOF to the other system                                */
/*--------------------------------------------------------------------*/

short geofpkt( void )
{
   if ((*sendpkt)("", 0))          /* Empty packet == EOF              */
      return DCP_FAILED;
   else
      return DCP_OK;
} /* geofpkt */

/*--------------------------------------------------------------------*/
/*    g w r m s g                                                     */
/*                                                                    */
/*    Send a message to remote system                                 */
/*--------------------------------------------------------------------*/

short gwrmsg( char *s )
{
   for( ; strlen(s) >= s_pktsize; s += s_pktsize)
   {
      short result = (*sendpkt)(s, (short) s_pktsize);
      if (result)
         return result;
   }

   return (*sendpkt)(s, (short) (strlen(s) + 1));
} /* gwrmsg */

/*--------------------------------------------------------------------*/
/*    g r d m s g                                                     */
/*                                                                    */
/*    Read a message from the remote system                           */
/*--------------------------------------------------------------------*/

short grdmsg( char *s)
{
   for ( ;; )
   {
      short len;
      short result = (*getpkt)( s, &len );
      if (result || (s[len-1] == '\0'))
         return result;
      s += len;
   } /* for */

} /* grdmsg */

/**********  Packet Machine  ********** RH Lamb 3/87 */

/*--------------------------------------------------------------------*/
/*    g m a c h i n e                                                 */
/*                                                                    */
/*    Ideally we would like to fork this process off in an            */
/*    infinite loop and send and receive packets through "inbuf"      */
/*    and "outbuf".  Can't do this in MS-DOS so we setup "getpkt"     */
/*    and "sendpkt" to call this routine often and return only        */
/*    when the input buffer is empty thus "blocking" the packet-      */
/*    machine task.                                                   */
/*--------------------------------------------------------------------*/

static short gmachine(const short timeout )
{
   static time_t idletimer = 0;

   boolean done   = FALSE;    /* True = drop out of machine loop  */
   boolean close  = FALSE;    /* True = terminate connection upon
                                        exit                      */
   boolean inseq  = TRUE;     /* True = Count next out of sequence
                                        packet as an error           */
   while ( !done )
   {
      boolean resend = FALSE;    /* True = resend data packets       */
      boolean donak  = FALSE;    /* True = NAK the other system      */
      unsigned long packet_no = remote_stats.packets;

      short pkttype, rack, rseq, rlen, rbuf, i1;
      time_t now;

#ifdef UDEBUG
      if ( debuglevel >= 7 )     /* Optimize processing a little bit */
      {

         printmsg(10, "* send %d %d < W < %d %d, "
                      "receive %d %d < W < %d, "
                      "error %d, packet %d",
            swl, sbl, swu, sbu, rwl, rbl, rwu, nerr,
            (long) remote_stats.packets);

/*--------------------------------------------------------------------*/
/*    Waiting for ACKs for swl to swu-1.  Next pkt to send=swu        */
/*    rwl=expected pkt                                                */
/*--------------------------------------------------------------------*/

      }
#endif

/*--------------------------------------------------------------------*/
/*             Attempt to retrieve a packet and handle it             */
/*--------------------------------------------------------------------*/

      pkttype = grpack(&rack, &rseq, &rlen, inbuf[nextbuf(rbl)], timeout);
      time(&now);
      switch (pkttype) {

         case CLOSE:
            remote_stats.packets++;
            printmsg(GDEBUG, "**got CLOSE");
            close = done = TRUE;
            break;

         case DCP_EMPTY:
            printmsg(timeout ? GDEBUG : 8, "**got EMPTY");

            if (bmodemflag[MODEM_CD] && !CD())
            {
               printmsg(0,"gmachine: Modem carrier lost");
               nerr++;
               close = TRUE;
            }

            if ( terminate_processing )
            {
               printmsg(0,"gmachine: User aborted processing");
               close = TRUE;
            }

            if (ftimer[sbl])
            {
#ifdef UDEBUG
               printmsg(6, "---> seq, elapst %d %ld", sbl,
                    ftimer[sbl] - now);
#endif
               if ( ftimer[sbl] <= (now - M_gPacketTimeout))
               {
                   printmsg(4, "*** timeout %d (%ld)",
                               sbl, (long) remote_stats.packets);
                       /* Since "g" is "go-back-N", when we time out we
                          must send the last N pkts in order.  The generalized
                          sliding window scheme relaxes this reqirment. */
                   nerr++;
                   timeouts++;
                   resend = TRUE;
               } /* if */
            } /* if */

            done = TRUE;
            break;

         case DATA:
            printmsg(5, "**got DATA %d %d", rack, rseq);
            i1 = nextpkt(rwl);   /* (R+1)%8 <-- -->(R+W)%8 */
            if (i1 == rseq) {
               lazynak--;
               remote_stats.packets++;
               idletimer = now;
               rwl = i1;
               rbl = nextbuf( rbl );
               inseq = arrived[rbl] = TRUE;
               inlen[rbl] = rlen;
               printmsg(5, "*** ACK d %d %d", rwl, rbl);
               gspack(ACK, rwl, 0, 0, 0, NULL);
               done = TRUE;   /* return to caller when finished      */
                              /* in a mtask system, unneccesary      */
            } else {
               if (inseq || ( now > (idletimer + M_gPacketTimeout)))
               {
                  donak = TRUE;  /* Only flag first out of sequence
                                    packet as error, since we know
                                    following ones also bad             */
                  outsequence++;
                  inseq = FALSE;
               }
               printmsg(GDEBUG, "*** unexpect %d ne %d (%d - %d)",
                                       rseq, i1, rwl, rwu);
            } /* else */

            if ( swl == swu )       /* We waiting for an ACK?     */
               break;               /* No --> Skip ACK processing */
            /* else Fall through to ACK case */

         case NAK:
         case ACK:
            if (pkttype == NAK)
            {
               nerr++;
               naksin++;
               printmsg(5, "**got NAK %d", rack);
               resend = TRUE;
            }
            else if (pkttype == ACK)
               printmsg(5, "**got ACK %d", rack);

            while(between(swl, rack, swu))
            {                             /* S<-- -->(S+W-1)%8 */
               remote_stats.packets++;
               printmsg(5, "*** ACK %d", swl);
               ftimer[sbl] = 0;
               idletimer = now;
               nbuffers--;
               done = TRUE;            /* Get more data for input */
               swl = nextpkt(swl);
               sbl = nextbuf(sbl);
            } /* while */

            if (!done && (pkttype == ACK)) /* Find packet?         */
            {
               printmsg(GDEBUG,"*** ACK for bad packet %d (%d - %d)",
                           rack, swl, swu);
            } /* if */
            break;

         case DCP_ERROR:
            printmsg(GDEBUG, "*** got BAD CHK");
            naksout++;
            donak = TRUE;
            lazynak = 0;               /* Always NAK bad checksum */
            break;

         default:
            screwups++;
            nerr++;
            printmsg(GDEBUG, "*** got SCREW UP");
            break;

      } /* switch */

/*--------------------------------------------------------------------*/
/*      If we received an NAK or timed out, resend data packets       */
/*--------------------------------------------------------------------*/

      if ( resend )
      for (rack = swl,
           rbuf = sbl;
           between(swl, rack, swu);
           rack = nextpkt(rack), rbuf = nextbuf( rbuf ))
      {                          /* resend rack->(swu-1)             */
         resends++;

         if ( outbuf[rbuf] == NULL )
         {
            printmsg(0,"gmachine: Transmit of NULL packet (%d %d)",
                     rwl, rbuf);
            panic();
         }

         if ( xmitlen[rbuf] == 0 )
         {
            printmsg(0,"gmachine: Transmit of 0 length packet (%d %d)",
                     rwl, rbuf);
            panic();
         }

         gspack(DATA, rwl, rack, outlen[rbuf], xmitlen[rbuf], outbuf[rbuf]);
         printmsg(5, "*** resent %d", rack);
         idletimer = ftimer[rbuf] = now;
      } /* for */

/*--------------------------------------------------------------------*/
/*  If we have an error and have not recently sent a NAK, do so now.  */
/*  We then reset our counter so we receive at least a window full of */
/*                 packets before sending another NAK                 */
/*--------------------------------------------------------------------*/

      if ( donak )
      {
         nerr++;
         if ( (lazynak < 1) || (now > (idletimer + M_gPacketTimeout)))
         {
            printmsg(5, "*** NAK d %d", rwl);
            gspack(NAK, rwl, 0, 0, 0, NULL);
            naksout++;
            idletimer = now;
            lazynak = nwindows + 1;
         } /* if ( lazynak < 1 ) */
      } /* if ( donak ) */

/*--------------------------------------------------------------------*/
/*                   Update error counter if needed                   */
/*--------------------------------------------------------------------*/

      if ((close || (packet_no != remote_stats.packets)) && (nerr > 0))
      {
         printmsg(GDEBUG,"gmachine: Packet %ld had %ld errors during transfer",
                     remote_stats.packets, (long) nerr);
         remote_stats.errors += nerr;
         nerr = 0;
      }

/*--------------------------------------------------------------------*/
/*    If we have an excessive number of errors, drop out of the       */
/*    loop                                                            */
/*--------------------------------------------------------------------*/

      if (nerr >= M_MaxErr)
      {
         printmsg(0,
            "gmachine: Consecutive error limit of %d exceeded, %d total errors",
            M_MaxErr, nerr + remote_stats.errors);
         done = close = TRUE;
         gstats();
      }
   } /* while */

/*--------------------------------------------------------------------*/
/*    Return to caller, gracefully terminating packet machine if      */
/*    requested                                                       */
/*--------------------------------------------------------------------*/

   if ( close )
   {
      gspack(CLOSE, 0, 0, 0, 0, NULL);
      return CLOSE;
   }
   else
      return POK;

} /*gmachine*/


/*************** FRAMING *****************************/

/*
   g s p a c k

   Send a packet

   type=type yyy=pkrec xxx=timesent len=length<=s_pktsize data=*data
   ret(0) always
*/

static void gspack(short type,
                   short yyy,
                   short xxx,
                   short len,
                   unsigned short xmit,
#if defined(BIT32ENV)
                   char *data)
#else
                   char UUFAR *input)
#endif
{
   unsigned short check, i;
   unsigned char header[HDRSIZE];

#if !defined(BIT32ENV)
   char *data;                   // Local data buffer address
   if ( input == NULL )
      data = NULL;               // Make consistent with real buffer
   else {                        // Only copy if non-NULL
      data = gspkt;
      MEMCPY( data, input, xmit );
   }
#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -