示例#1
0
static void altmain()
{
    // Gain access to argv.
    extern char **environ;
    char **argv = environ -2;

    // Don't run again if the parent restarted.
    if (getenv("XSERVERPINGER"))
        return;
    putenv((char *)"XSERVERPINGER=1");

    // Start a new process and let our parent (the real mcompositor) go.
    if (fork())
        return;

    // Distinguish ourselves from the real mcompositor and die with it.
    strcpy(argv[0], "xserverping");
    prctl(PR_SET_NAME, "xserverping");
    prctl(PR_SET_PDEATHSIG, SIGTERM);

    int meh = 0;
    QCoreApplication app(meh, 0);

    XServerPinger pinger(2500);
    app.exec();
    exit(0);
}
bool CommandLine::Parse(int argc, char* argv[])
{
    namespace po = boost::program_options;
    // Declare the supported options.
    std::wcout << std::boolalpha;
    try
    {
        po::options_description general("General options");
        general.add_options()
            ("help,h", "produce help message")
            ("no-pinger", "Dont be a pinger (default is to be a pinger and a ponger)")
            ("no-ponger", "Dont be a ponger (default is to be a pinger and a ponger)")
            ;

        po::options_description pinger("Pinger options");
        pinger.add_options()
            ("num-instances,i", po::value<int>(&m_numInstances)->default_value(1), "The number of instances to use")
            ("payload,p", "Add payload of random size to Ping")
            ("timeout,t", po::value<int>(&m_timeout)->default_value(20),"Timeout before missing pongs should generate error report")
            ;


        //merge options into one.
        po::options_description all ("Allowed options");
        all.add(general).add(pinger);

        po::store(po::parse_command_line(argc,argv,all),m_variablesMap);
        po::notify(m_variablesMap);

        if (m_variablesMap.count("help"))
        {
            std::wcout << all << std::endl;
            return false;
        }

        m_noPinger = 0 != m_variablesMap.count("no-pinger");
        m_noPonger = 0 != m_variablesMap.count("no-ponger");
        m_payload = 0 != m_variablesMap.count("payload");
    }
    catch (const std::exception & e)
    {
        std::wcerr << "Parse of command line failed: " << std::endl
            << e.what() << std::endl;
        return false;
    }
    return true;
}
示例#3
0
static void altmain()
{
    // Don't run again if the parent restarted.
    if (getenv("XSERVERPINGER"))
        return;
    putenv("XSERVERPINGER=1");

    // Start a new process and let our parent (the real mcompositor) go.
    if (fork())
        return;

    // Die with the parent.
    prctl(PR_SET_PDEATHSIG, SIGTERM);

    int meh = 0;
    QCoreApplication app(meh, 0);

    XServerPinger pinger(2500);
    app.exec();
    exit(0);
}
示例#4
0
void main_loop(int icmp_sock, __u8 *packet, int packlen)
{
	char addrbuf[128];
	char ans_data[4096];
	struct iovec iov;
	struct msghdr msg;
	struct cmsghdr *c;
	int cc;
	int next;
	int polling;

	iov.iov_base = (char *)packet;

	for (;;) {
		/* Check exit conditions. */
		if (exiting)
			break;
		if (npackets && nreceived + nerrors >= npackets)
			break;
		if (deadline && nerrors)
			break;
		/* Check for and do special actions. */
		if (status_snapshot)
			status();

		/* Send probes scheduled to this time. */
		do {
			next = pinger();
			next = schedule_exit(next);
		} while (next <= 0);

		/* "next" is time to send next probe, if positive.
		 * If next<=0 send now or as soon as possible. */

		/* Technical part. Looks wicked. Could be dropped,
		 * if everyone used the newest kernel. :-)
		 * Its purpose is:
		 * 1. Provide intervals less than resolution of scheduler.
		 *    Solution: spinning.
		 * 2. Avoid use of poll(), when recvmsg() can provide
		 *    timed waiting (SO_RCVTIMEO). */
		polling = 0;
		if ((options & (F_ADAPTIVE|F_FLOOD_POLL)) || next<SCHINT(interval)) {
			int recv_expected = in_flight();

			/* If we are here, recvmsg() is unable to wait for
			 * required timeout. */
			if (1000 % HZ == 0 ? next <= 1000 / HZ : (next < INT_MAX / HZ && next * HZ <= 1000)) {
				/* Very short timeout... So, if we wait for
				 * something, we sleep for MININTERVAL.
				 * Otherwise, spin! */
				if (recv_expected) {
					next = MININTERVAL;
				} else {
					next = 0;
					/* When spinning, no reasons to poll.
					 * Use nonblocking recvmsg() instead. */
					polling = MSG_DONTWAIT;
					/* But yield yet. */
					sched_yield();
				}
			}

			if (!polling &&
			    ((options & (F_ADAPTIVE|F_FLOOD_POLL)) || interval)) {
				struct pollfd pset;
				pset.fd = icmp_sock;
				pset.events = POLLIN|POLLERR;
				pset.revents = 0;
				if (poll(&pset, 1, next) < 1 ||
				    !(pset.revents&(POLLIN|POLLERR)))
					continue;
				polling = MSG_DONTWAIT;
			}
		}

		for (;;) {
			struct timeval *recv_timep = NULL;
			struct timeval recv_time;
			int not_ours = 0; /* Raw socket can receive messages
					   * destined to other running pings. */

			iov.iov_len = packlen;
			memset(&msg, 0, sizeof(msg));
			msg.msg_name = addrbuf;
			msg.msg_namelen = sizeof(addrbuf);
			msg.msg_iov = &iov;
			msg.msg_iovlen = 1;
			msg.msg_control = ans_data;
			msg.msg_controllen = sizeof(ans_data);

			cc = recvmsg(icmp_sock, &msg, polling);
			polling = MSG_DONTWAIT;

			if (cc < 0) {
				if (errno == EAGAIN || errno == EINTR)
					break;
				if (!receive_error_msg()) {
					if (errno) {
						perror("ping: recvmsg");
						break;
					}
					not_ours = 1;
				}
			} else {

#ifdef SO_TIMESTAMP
				for (c = CMSG_FIRSTHDR(&msg); c; c = CMSG_NXTHDR(&msg, c)) {
					if (c->cmsg_level != SOL_SOCKET ||
					    c->cmsg_type != SO_TIMESTAMP)
						continue;
					if (c->cmsg_len < CMSG_LEN(sizeof(struct timeval)))
						continue;
					recv_timep = (struct timeval*)CMSG_DATA(c);
				}
#endif

				if ((options&F_LATENCY) || recv_timep == NULL) {
					if ((options&F_LATENCY) ||
					    ioctl(icmp_sock, SIOCGSTAMP, &recv_time))
						gettimeofday(&recv_time, NULL);
					recv_timep = &recv_time;
				}

				not_ours = parse_reply(&msg, cc, addrbuf, recv_timep);
			}

			/* See? ... someone runs another ping on this host. */
			if (not_ours && !using_ping_socket)
				install_filter();

			/* If nothing is in flight, "break" returns us to pinger. */
			if (in_flight() == 0)
				break;

			/* Otherwise, try to recvmsg() again. recvmsg()
			 * is nonblocking after the first iteration, so that
			 * if nothing is queued, it will receive EAGAIN
			 * and return to pinger. */
		}
	}
	finish();
}
示例#5
0
文件: main.cpp 项目: mjvd/personal
//=================================================================================================
int main(int argc, char* argv[])
{
    try
    {
        int  maxHistogramValue;
        int  idealCutoff;
        int  pingPeriod;
        int  statsPeriod;
        std::string dest;

        po::options_description desc("Allowed options");
        desc.add_options()
            ("help",                                                                            "produce help message")
            ("verbose",                                                                         "display the RTT of each packet")
            ("precise",                                                                         "display the RTT of each packet down to the micro-second")
            ("dest",                po::value<std::string>(&dest),                              "hostname or IPv4 address of destination")
            ("max-histogram-value", po::value<int> (&maxHistogramValue) ->default_value(400),   "must be one of {200,400,600,800,1000}")
            ("ideal-cutoff",        po::value<int> (&idealCutoff)       ->default_value(80),    "displays percentage of all packets with RTT lower than this cutoff")
            ("ping-period",         po::value<int> (&pingPeriod)        ->default_value(200),   "how often to send each ping packet (in milli-seconds)")
            ("stats-period",        po::value<int> (&statsPeriod)       ->default_value(10),    "how often to produce the statistics (in minutes)")
            ;

        // we will support one and only 1 positional option - which is the destination
        po::positional_options_description pd;
        pd.add("dest", 1);

        // process the command line
        po::variables_map vm;
        po::store(po::command_line_parser(argc, argv).options(desc).positional(pd).run(), vm);
        po::notify(vm);

        if (argc <= 1 || vm.count("help"))
        {
            std::cout
                << "\n                                                                           "
                << "\nMicroPinger                                                                "
                << "\n                                                                           "
                << "\n" << desc
                << "\n                                                                           "
                << "\n                                                                           "
                << "\n  TIMING PRECISION:                                                        " 
                << "\n  This application was specifically designed to calculate the RTT as       "
                << "\n  accurately as possible.  This app uses the QueryPerformanceCounter API,  "
                << "\n  and as such, the timestamps that are generated when we send and receive  "
                << "\n  each packet should be accurate to within a few of micro-seconds.  The    "
                << "\n  app is based on the Boost.Asio network library, and packets are handled  " 
                << "\n  asynchronously.  There is no polling here to introduce any delays.       "
                << "\n                                                                           "
                << "\n  Note that these 'micro-second accurate' RTT for the ping packets will    "
                << "\n  of course include delays due to the packet traversing this app, the local"
                << "\n  network stack, and other delays due to the operating system itself.      "
                << "\n                                                                           "
                << "\n                                                                           "
                << "\n  NOTES:                                                                   "
                << "\n    * If any packet takes more than 1 second to come back, it will be      "
                << "\n      considered to have timed-out.                                        "
                << "\n    * This app sends only a single packet at any time, then waits for up   "
                << "\n      to 1 second for the response.                                        "
                << "\n    * Packets are throttled to a maximum rate as specified on the command  "
                << "\n      line in the <pingPeriod> parameter.                                  "
                << "\n    * For best viewing, maximize your console window.                      "
                << "\n    * This application uses raw sockets, therefore it must be run with     "
                << "\n      administrator privileges.                                            "
                << "\n                                                                           "
                << "\n                                                                           "
                << "\n  PROTOCOL SUPPORT:                                                        "
                << "\n  This application supports ICMP over IPv4.  It does not support IPv6.     "
                << "\n                                                                           "
                << "\n                                                                           "
                << std::endl;
            return EXIT_FAILURE;
        }

        if (dest.empty())                           { std::cout << "ERROR:  you must specify a destination" << std::endl; return EXIT_FAILURE; }
        if (idealCutoff < 1 || idealCutoff > 1000)  { std::cout << "ERROR:  ideal-cutoff is invalid"        << std::endl; return EXIT_FAILURE; }
        if (pingPeriod < 1 || pingPeriod > 60000)   { std::cout << "ERROR:  ping-period is invalid"         << std::endl; return EXIT_FAILURE; }
        if (maxHistogramValue < 200 || maxHistogramValue > 1000 || (maxHistogramValue % 200 != 0)) { std::cout << "ERROR:  max-histogram-value is invalid" << std::endl;  return EXIT_FAILURE; }

        auto verbose = vm.count("verbose") == 1;
        auto precise = vm.count("precise") == 1;

        boost::asio::io_service io_service;
        mvd::Pinger pinger(io_service, dest, pingPeriod, statsPeriod, verbose, precise, maxHistogramValue, idealCutoff);
        io_service.run();
        return EXIT_SUCCESS;
    }
    catch (std::exception& e)
    {
        std::cout << "ERROR:  std::exception caught in main():  " << e.what() << std::endl;
        assert(false);
        return EXIT_FAILURE;
    }
    catch (...)
    {
        std::cout << "ERROR:  unknown exception caught in main()" << std::endl;
        assert(false);
        return EXIT_FAILURE;
    }
}
示例#6
0
文件: ping.c 项目: wda2945/Libraries
/* returns  0 - not an echo
* returns  1 - our echo
* returns -1 - not ours
*/
int pingServer(char *target)
{
	struct sockaddr_in from;
	struct timeval intvl;
	struct iovec iov;

	struct msghdr msg;
	u_char packet[IP_MAXPACKET];
	char *source;

	struct sockaddr_in *to;

	int  hold,  icmp_len, sockerrno;


	source = NULL;

	s = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
	sockerrno = errno;

	outpack = outpackhdr + sizeof(struct_ip);

	icmp_len = sizeof(struct_ip) + ICMP_MINLEN + phdr_len;

	maxpayload = IP_MAXPACKET - icmp_len;
	if (datalen > maxpayload)
		errx(EX_USAGE, "packet size too large: %d > %d", datalen,
				maxpayload);
	send_len = icmp_len + datalen;

	bzero(&whereto, sizeof(whereto));
	to = &whereto;
	to->sin_family = AF_INET;
	//	to->sin_len = sizeof *to;
	if (inet_aton(target, &to->sin_addr) != 0) {
		hostname = target;
	}

	if (datalen >= TIMEVAL_LEN)	/* can we time transfer */
		timing = 1;

	ident = getpid() & 0xFFFF;

	if (s < 0) {
		errno = sockerrno;
		err(EX_OSERR, "socket");
	}
	hold = 1;

#ifdef SO_TIMESTAMP
	{ int on = 1;
	if (setsockopt(s, SOL_SOCKET, SO_TIMESTAMP, &on, sizeof(on)) < 0)
		err(EX_OSERR, "setsockopt SO_TIMESTAMP");
	}
#endif

	/*
	 * XXX receive buffer needs undetermined space for mbuf overhead
	 * as well.
	 */
	hold = IP_MAXPACKET + 128;
	(void)setsockopt(s, SOL_SOCKET, SO_RCVBUF, (char *)&hold,
			sizeof(hold));
	if (uid == 0)
		(void)setsockopt(s, SOL_SOCKET, SO_SNDBUF, (char *)&hold,
				sizeof(hold));

	if (to->sin_family == AF_INET) {
		(void)printf("PING %s (%s)", hostname,
				inet_ntoa(to->sin_addr));
		if (source)
			(void)printf(" from %s", shostname);
		(void)printf(": %d data bytes\n", datalen);
	} else
		(void)printf("PING %s: %d data bytes\n", hostname, datalen);

	bzero(&msg, sizeof(msg));
	msg.msg_name = (caddr_t)&from;
	msg.msg_iov = &iov;
	msg.msg_iovlen = 1;
	iov.iov_base = packet;
	iov.iov_len = IP_MAXPACKET;

	pinger();		/* send the ping */

	(void)gettimeofday(&last, NULL);

	intvl.tv_sec = interval / 1000;
	intvl.tv_usec = interval % 1000 * 1000;

	while(1)
	{
		struct timeval now, timeout;
		fd_set rfds;
		int cc, n;

		if ((unsigned)s >= FD_SETSIZE)
			errx(EX_OSERR, "descriptor too large");
		FD_ZERO(&rfds);
		FD_SET(s, &rfds);
		(void)gettimeofday(&now, NULL);
		timeout.tv_sec = last.tv_sec + intvl.tv_sec - now.tv_sec;
		timeout.tv_usec = last.tv_usec + intvl.tv_usec - now.tv_usec;
		while (timeout.tv_usec < 0) {
			timeout.tv_usec += 1000000;
			timeout.tv_sec--;
		}
		while (timeout.tv_usec >= 1000000) {
			timeout.tv_usec -= 1000000;
			timeout.tv_sec++;
		}
		if (timeout.tv_sec < 0)
			timeout.tv_sec = timeout.tv_usec = 0;
		n = select(s + 1, &rfds, NULL, NULL, &timeout);
		if (n < 0)
			continue;	/* Must be EINTR. */
		else if (n == 1) {
			struct timeval *tv = NULL;
			msg.msg_namelen = sizeof(from);
			if ((cc = recvmsg(s, &msg, 0)) < 0) {
				if (errno == EINTR)
					continue;
				warn("recvmsg");
				continue;
			}

			if (tv == NULL) {
				(void)gettimeofday(&now, NULL);
				tv = &now;
			}

			int reply = pr_pack((char *)packet, cc, &from, tv);
			if (reply >= 0) return reply;
		}
		else return 0;
	}
	return 0;
}