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 + -
显示快捷键?