📄 pinglib.c
字号:
sprintf (tName, "tPingTx%d", seq); /* assign unique Tx task name */ if ((pPS->idTx = taskSpawn (tName, txPriority, 0, 6000, (FUNCPTR) pingTx, (int) pPS, (int) &to, txInterval, 0,0,0,0,0,0,0)) == ERROR) pingError (pPS); /* receive echo reply packets from remote host */ while (!pPS->numPacket || (pPS->numRx != pPS->numPacket)) { if ((ix = recvfrom (pPS->pingFd, (char *) pPS->bufRx, PING_MAXPACKET, 0, (struct sockaddr *) &from, &fromlen)) == ERROR) { if (errno == EINTR) continue; break; } if (ix == 0 && pPS->idTimeout == NULL) /* shutdown from timeout ? */ { if (options & PING_OPT_DEBUG) printf ("ping: timeout\n"); errno = S_pingLib_TIMEOUT; /* timeout error */ break; } if ((wdStart (pPS->wdTimeout, txTmo, (FUNCPTR) semGive, (int) pPS->semIdTimeout)) == ERROR) /* start timeout watchdog */ break; pingRxPrint (pPS, ix, &from); /* printout Rx info */ } if (pPS->numRx > 0) status = OK; /* host is reachable */release: /* error encountered */ pingFinish (taskTcb (pPS->idRx)); /* cleanup & print end stats */ return (status); }/********************************************************************************* pingTx - send ICMP echo request packets to a remote host* * This routine sends ICMP echo request packets to the remote host* specified by the structure pointed to by <toAddr>. Each packet* is given a sequence number and a current tick count, so that a* roundtrip time may be computed.** RETURNS:* N/A.*/LOCAL void pingTx ( PING_STAT * pPS, /* ping stats structure */ struct sockaddr * toAddr, /* remote host address */ int delay /* delay between Tx packets */ ) { int ix; while (1) /* FOREVER */ { *pPS->pBufTime = tickGet (); /* load current tick count */ pPS->pBufIcmp->icmp_seq = pPS->numTx++; /* increment seq number */ pPS->pBufIcmp->icmp_cksum = 0; pPS->pBufIcmp->icmp_cksum = checksum ((u_short *) pPS->pBufIcmp, _pingTxLen); /* checksum new packet */ /* transmit ICMP packet */ if ((ix = sendto (pPS->pingFd, (char *) pPS->pBufIcmp, _pingTxLen, 0, toAddr, sizeof (struct sockaddr))) != _pingTxLen) if (pPS->flags & PING_OPT_DEBUG) printf ("ping: wrote %s %d chars, ret=%d\n", pPS->toHostName, _pingTxLen, ix); taskDelay (delay); /* wait Tx interval */ } }/********************************************************************************* pingRxPrint - print out information about a received packet** This routine prints out information about a received ICMP echo reply* packet. First, the packet is checked for minimum length and* correct message type and destination.** RETURNS:* N/A.*/LOCAL void pingRxPrint ( PING_STAT * pPS, /* ping stats structure */ int len, /* Rx message length */ struct sockaddr_in *from /* Rx message address */ ) { struct ip * ip = (struct ip *) pPS->bufRx; long * lp = (long *) pPS->bufRx; struct icmp * icp; int ix; int hlen; int triptime; ulong_t now = tickGet(); char fromHostName [MAXHOSTNAMELEN + 1]; char fromInetName [INET_ADDR_LEN]; /* convert address notation */ inet_ntoa_b (from->sin_addr, fromInetName); if ((hostGetByAddr (from->sin_addr.s_addr, fromHostName)) == ERROR) *fromHostName = NULL; /* hostname not found */ hlen = ip->ip_hl << 2; if (len < hlen + ICMP_MINLEN) /* at least min length ? */ { if (pPS->flags & PING_OPT_DEBUG) printf ("packet too short (%d bytes) from %s\n", len, fromInetName); return; } len -= hlen; /* strip IP header */ icp = (struct icmp *) (pPS->bufRx + hlen); if (icp->icmp_type != ICMP_ECHOREPLY) /* right message ? */ { if (pPS->flags & PING_OPT_DEBUG) /* debug odd message */ { if (*fromHostName != NULL) printf ("%d bytes from %s (%s): ", len, fromHostName, fromInetName); else printf ("%d bytes from %s: ", len, fromInetName); icp->icmp_type = min (icp->icmp_type, ICMP_TYPENUM); printf ("icmp_type=%d\n", icp->icmp_type); for(ix = 0; ix < 12; ix++) printf ("x%2.2lx: x%8.8lx\n", (unsigned long)ix * sizeof (long), *lp++); printf ("icmp_code=%d\n", icp->icmp_code); } return; } if (icp->icmp_id != (pPS->idRx & 0xffff)) return; /* wasn't our ECHO */ /* print out Rx packet stats */ if (!(pPS->flags & PING_OPT_SILENT) && pPS->numPacket != 1) { if (*fromHostName != NULL) printf ("%d bytes from %s (%s): ", len, fromHostName, fromInetName); else printf ("%d bytes from %s: ", len, fromInetName); printf ("icmp_seq=%d. ", icp->icmp_seq); triptime = (now - *((ulong_t *) icp->icmp_data)) * (1000 / pPS->clkTick); printf ("time=%d. ms\n", triptime); pPS->tSum += triptime; pPS->tMin = min (pPS->tMin, triptime); pPS->tMax = max (pPS->tMax, triptime); } pPS->numRx++; /* bump recv count */ }/********************************************************************************* pingTimeout - shutdown a ping socket** This routine performs a shutdown of a ping raw socket. It is called* before the ping session starts, and it immediately pends trying to* take a binary semaphore. Once the semaphore is given by the timeout* watchdog, this routine does a shutdown on the socket, thereby unblocking* the reader(s) of the socket.** RETURNS:* N/A.*/LOCAL void pingTimeout ( PING_STAT * pPS /* ping stats structure */ ) { semTake (pPS->semIdTimeout, WAIT_FOREVER); /* wait until tmo gives sem */ pPS->idTimeout = NULL; /* timeout happened */ (void) shutdown (pPS->pingFd, 0); /* shutdown ping socket */ }/********************************************************************************* pingFinish - return all allocated resources and print out final statistics** This routine returns all resources allocated for the ping session, and* prints out a stats summary.** The ping session is located in the session list (pingHead) by searching* the ping stats structure for the receiver task ID. This is necessary* because this routine is passed a pointer to the task control block, and does* not have ready access to the ping stats structure itself. This accomodates* the use of task delete hooks as a means of calling this routine.** RETURNS:* N/A.*/LOCAL void pingFinish ( WIND_TCB * pTcb /* pointer to task control block */ ) { PING_STAT * pPS; /* ping stats structure */ PING_STAT ** ppPrev; /* pointer to prev statNext */ semTake (pingSem, WAIT_FOREVER); /* get list access */ ppPrev = &pingHead; for (pPS = pingHead; (pPS != NULL) && (taskTcb (pPS->idRx) != pTcb); pPS = pPS->statNext) /* find session in list */ ppPrev = &pPS->statNext; if (pPS == NULL) /* session found ? */ { semGive (pingSem); /* give up list access */ return; } *ppPrev = pPS->statNext; /* pop session off list */ if (pingHead == NULL) (void) taskDeleteHookDelete ((FUNCPTR) pingFinish); semGive (pingSem); /* give up list access */ /* return all allocated/created resources */ if (pPS->wdTimeout) wdDelete (pPS->wdTimeout); if (pPS->semIdTimeout) semDelete (pPS->semIdTimeout); if (pPS->idTx) taskDelete (pPS->idTx); if (pPS->idTimeout) taskDelete (pPS->idTimeout); if (pPS->pingFd) (void) close (pPS->pingFd); if (!(pPS->flags & PING_OPT_SILENT)) /* print final report ? */ { if (pPS->numRx) /* received at least one ? */ { if (pPS->numPacket != 1) /* full report */ { printf ("----%s PING Statistics----\n", pPS->toHostName); printf ("%d packets transmitted, ", pPS->numTx); printf ("%d packets received, ", pPS->numRx); if (pPS->numTx) printf ("%d%% packet loss", ((pPS->numTx - pPS->numRx) * 100) / pPS->numTx); printf ("\n"); if (pPS->numRx) printf ("round-trip (ms) min/avg/max = %d/%d/%d\n", pPS->tMin, pPS->tSum / pPS->numRx, pPS->tMax); } else /* short report */ printf ("%s is alive\n", pPS->toHostName); } else printf ("no answer from %s\n", pPS->toHostName); } free ((char *) pPS); /* free stats memory space */ }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -