app_ping.c

来自「在ARM7和UC/OSII的平台上实现了GPS自动报站的功能,涉及GPS模块LE」· C语言 代码 · 共 763 行 · 第 1/2 页

C
763
字号
         return 0;
   }

   if (ping_times != 1)
      ns_printf(pio,"...use endping command to stop pinging...\n");

   /* Does the invoker of this command already has another ping going ? */
   p = ping_search((GEN_IO)pio);
   if ( p != NULL )
   {
      /* End the previous session */
      ns_printf(pio,"Terminating earlier ping operation.\n");
      ping_end(pio);
   }

   p = ping_new();
   if ( p == NULL )
   {
      dtrap("app_ping 3\n");
      ns_printf(pio,"Error allocating memory for new ping.\n");
      return PING_ST_ALLOC_ERR;
   }

   /* Now we are ready to use p */
   p->ipadd = ipadd ;   /* First assign the default IP addr */
   p->times = ping_times;
   p->pio   = (GEN_IO)pio;

   /* if it is ping-forever, then delay should be atleaast 2 timeticks */
   if ((p->times == 0) && (p->delay < 2))
   {
      p->delay=2;
      ns_printf(pio,"Ping delay is too low for continous pinging.\n");
      ns_printf(pio,"Hence delay for this session is %ld ms.\n", 
       p->delay*TIMEFOR1TICK);
   }

   e = ping_send(p); /* send 1st ping */

   TK_WAKE(&to_pingcheck);    /* wake ping task for later sends */

   return e;
}



/* FUNCTION: ping_send()
 * 
 * Send a single ping packet based on static parms.
 *  This should be called only after start_ping() has 
 * set things up. It's designed to be called from a timed polling 
 * routine until all the pings are sent.
 *
 * PARAM1: PING_INFO p
 *
 * RETURNS: 0 on success, or -1 if error
 */

int
ping_send(PING_INFO p)
{
   int   e;          /* error holder */

   /* We can have a variety of output devices thru pio mechanism. Eg. 
    * console, telnet client, etc. So consider the following scenario 
    * 1. InterNiche s/w with TELNET Server is running on 10.22 2. 
    * User (TELNET Client) does a TELNET connection from 10.20 3. 
    * User issues a ping-forever command. All ping output is being 
    * displayed in user's TELNET window. 4. User closes the TELNET 
    * client before terminating ping session. Now when PING 
    * application tries to display its output, it fails. In this case 
    * we close the ping session. 
    */
   if (ns_printf(p->pio,"ping %d to %s: ",p->out,print_ipad(p->ipadd)) == 0) 
   {
      /* Output device is no longer available for display */
      ping_delete(p);   /* shut off ping */
      return -1;
   }

   e = icmpEcho(p->ipadd, NULL, p->length, (unshort)p->out);

   p->times--;    /* count another one done */

   if (e == 0)
   {
      p->out++;
      ns_printf(p->pio,"ping %d sent...\n",p->out);
   }
   else if(e == ARP_WAITING)
   {
      ns_printf(p->pio,"Arping for host...\n");
      p->out++;
   }
   else
   {
      ns_printf(p->pio,"Ping send failure %d\n",e);
      ping_end(p->pio);    /* shut off ping */
      return -1;
   }
   p->nextping = cticks + p->delay;    /* set time for next ping */

   return 0;
}



/* FUNCTION: ping_end()
 *
 * End an ongoing ping session. Calls ping_delete() to free 
 * resources used for ping session.
 *
 * PARAM1: GEN_IO pio - device for console output
 *
 * RETURNS: SUCCESS or PING_END_NO_SESSION
 */

int
ping_end(void * pio)
{
   PING_INFO p;

   p = ping_search((GEN_IO)pio);
   if ( p == NULL )
   {
      ns_printf(pio,"No ongoing ping session found.\n");
      return PING_END_NO_SESSION;
   }

   if (p->out > 1)   /* print complete msg after multiple pings */
   {
      ns_printf(pio,"ping complete; sent %d, received %d\n",p->out,p->in);
   }

   ping_delete(p);

   return SUCCESS;
}


/* FUNCTION: pingUpcall()
 *
 * called from ICMPO layer when we receive an icmpEchoReply.
 *
 * PARAM1: PACKET p -  Pointer to the received packet (IN)
 *
 * RETURNS: Should return the usual upcall codes: 0 if 
 * OK, ENP_NOT_MINE (1) if packet is not of interest, or a negative 
 * error code. 
 */

int
pingUpcall(PACKET p)
{
   putq(&pingRcvq, (q_elt)p);

#ifndef SUPERLOOP
   /* On multitask systems wake the ping receiver task */
   TK_WAKE(&to_pingcheck);
#endif   /* SUPERLOOP */

   return 0;
}


/* FUNCTION: ping_recv()
 * 
 * Check the status of various ping sessions. If a response has come,
 * display it to appropriate caller. Send more ping packets (if needed).
 * This should be polled regularly - i.e. from tk_yield() - if the pingUpcall() 
 * routine above is used.
 *
 * PARAM1: none
 *
 * RETURNS: void
 */

extern   char *   pingdata;   /* default ping data in ..\inet\ping.c */
static int in_pingcomp = 0;   /* re-entrancy guard */

void
ping_recv(void)
{
   PACKET pkt;
   struct ping *  pp;
   u_char * pdata;
   int   i, dataend, pdlen;
   int   data_len;      /* length of DATA in recived ping */
   int   save_seq;
   ip_addr save_host;
   PING_INFO p;

   /* Process all the replies that have come */
   while (pingRcvq.q_len)
   {
      pkt = (PACKET)getq(&pingRcvq);
      if (!pkt)
         panic("ping_check: no pkt");
      pp = (struct ping *)pkt->nb_prot;

      /* the upcalled packet included the ICMP header. Strip this off
       * for the purposes of reporting data size
       */
      data_len = pkt->nb_plen -= sizeof(struct ping);
      save_seq = (unsigned)pp->pseq;
      save_host = pkt->fhost;

      /* If the ping data fields looks like one of our defaults, verify
       * the contents. This relies on the code in ..\inet\ping.c
       */
      pdata = (u_char*)(pp+1);   /* pointer to ping data */
      pdlen = strlen(pingdata);
      if (strncmp(pingdata, (char*)pdata, pdlen) == 0)
      {
         pdata += pdlen;      /* point past verified text */
         dataend = pkt->nb_plen - pdlen;
         for (i = pdlen; i < dataend; i++)
         {
            if (*pdata++ != (u_char)(i & 0xFF))
            {
               dprintf("ping data mismatch at byte %u\n", 
                i + pdlen + sizeof(struct ping) );
               break;
            }
         }
      }
      LOCK_NET_RESOURCE(FREEQ_RESID);
      pk_free(pkt);
      UNLOCK_NET_RESOURCE(FREEQ_RESID);

      /* Output the result at the caller's output device */
      /* For that, first find out the sender of this ping */

      p = ping_demux(save_host) ;
      if ( p != NULL )
      {
         p->in++;
         if ( ns_printf(p->pio,"got ping reply; data len :%d seq %d from %s\n",
            data_len, save_seq, print_ipad(save_host)) == 0 )
         {
            /* Output device is no longer available for display */
            ping_delete(p);   /* shut off ping */
         }
         if (ns_printf(p->pio,prompt) == 0)
         {
            /* Output device is no longer available for display */
            ping_delete(p);   /* shut off ping */
         }
         
      }
#ifndef TESTMENU  /* don't flood console if testing */
      else
      {
         dprintf("Could not find invoker of ping %s\n",print_ipad(pkt->fhost));
      }
#endif
   }
}



/* FUNCTION: ping_check()
 * 
 * PARAM1: none
 *
 * RETURNS: void
 */

void
ping_check(void)
{
   PING_INFO p = pingq;
   PING_INFO nextp;
   GEN_IO pio;

   if (in_pingcomp)  /* guard against re-entry */
      return;
   in_pingcomp++;    /* set re-entry flag */

#ifdef SUPERLOOP
   ping_recv();   /* if superloop, check receives here */
#endif

   /* Send more ping packets, if so configured. */
   while (p)
   {
      nextp = p->next ;
      if ((p->nextping != 0) && (p->nextping <= cticks))
      {
         if (p->times != 0)
         {
            ping_send(p);
         }
         else
         {
            pio = p->pio;
            ns_printf(pio, prompt); /* print prompt before p->pio is freed */
            ping_end(pio);            
         }
      }
      p = nextp;
   }

   in_pingcomp--;    /* clear re-entry flag */
}


/* FUNCTION: ping_demux()
 * 
 * Find out the PingInfo structure 
 * corresponding to the received packet. This is tricky ,because we 
 * just know the source of the ping reply. So we need to go through 
 * the ping session list and find out the session that pinged to this 
 * IP address. Pitfalls : Say if two telnet sessions ping to the same 
 * host at the same time, and the destination replies, output of ping 
 * will always go to the first telnet session !!!
 *
 * PARAM1: ip_addr fhost - IP addres of machine that sent the ping reply (IN)
 *
 * RETURNS: Pointer to PingInfo structure or NULL 
 */

PING_INFO 
ping_demux(ip_addr fhost)
{
   PING_INFO p=pingq;

   while ( p )
   {
      if ( p->ipadd == fhost )
         break;
      else
         p=p->next;
   }

   return p;
}




/* FUNCTION: ping_stats()
 * 
 * Display statistics about ping sessions.
 *
 * PARAM1: GEN_IO pio - device for console output
 *
 * RETURNS: 0 on success, or one of the PING error codes
 */

int
ping_stats(void * pio)
{
   PING_INFO p=pingq;
   int   cnt=0;

   ns_printf(pio,"Default ping delay time:  %ld ms.\n", 
    pingdelay*TIMEFOR1TICK);
   ns_printf(pio,"Default ping host: %s\n", print_ipad(activehost));
   ns_printf(pio,"Default ping data length: %u bytes\n", deflength);

   while (p)
   {
      cnt++;
      ns_printf(pio,"Statistics about pinging %s\n",
       print_ipad(p->ipadd) );
      ns_printf(pio,"Times=%ld, Length=%d, Delay=%ld\n",
       p->times, p->length, p->delay*TIMEFOR1TICK );
      ns_printf(pio,"Packets : sent=%d, received=%d\n\n",
       p->out, p->in);
      p=p->next;
   }

   ns_printf(pio,"There are %d ongoing ping sessions.\n",cnt);

   return SUCCESS;
}

#endif   /* PING_APP */

⌨️ 快捷键说明

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