int main ( int argc, char ** argv ) { char optChar; char * target; int optindx = 0; int interval = 0; int count = -1; int timeout = ICMP_TIMEOUT_SECS; bool debug = false; size_t size = 0; timeval tvin, tvsnt, tvo; static struct option l_opts[] = { {"count", required_argument, 0, 'c'}, {"debug", no_argument, 0, 'd'}, {"interval", required_argument, 0, 'i'}, {"help", no_argument, 0, 'h'}, {"size", required_argument, 0, 's'}, {"version", no_argument, 0, 'v'}, {0,0,0,0} }; if ( argc < 2 ) usage(); while ( (optChar = getopt_long(argc, argv, "c:di:hs:v", l_opts, &optindx)) != EOF ) { switch ( optChar ) { case 'c': count = StringUtils::FromString<int>(optarg); break; case 'd': debug = true; break; case 'i': interval = StringUtils::FromString<int>(optarg); break; case 'h': usage(); break; case 's': size = StringUtils::FromString<size_t>(optarg); break; case 'v': version(); break; default: usage(); break; } } target = strdup(argv[argc-1]); ::memset(&tvsnt, 0, sizeof(tvsnt)); ::memset(&tvin, 0, sizeof(tvin)); ::memset(&tvo, 0, sizeof(tvo)); if ( interval == 0 ) interval = 1000; std::string host = target; ::free(target); Pid = ::getpid() & 0xFFFF; ::signal(SIGPIPE, SIG_IGN); ::signal(SIGINT, &sigHandler); ipv4addr_t dstaddr = AddrInfo::GetHostAddr(host); if ( dstaddr == 0 ) { std::cout << "Invalid target host: " << host << std::endl; exit(-1); } Socket * icmps = new Socket(dstaddr, SOCKET_ICMP, SOCKTYPE_RAW, SOCKET_ICMP); icmps->init(false); dropPriv(); neticmp_h * req = NULL; icmp_ts * its = NULL; char * wptr = NULL; char * wbuff = NULL; char * data = NULL; const char * dt = NULL; bool sendReq = true; sockaddr_t csock; sockaddr_in* sa; ipv4addr_t addr; size_t sz, buflen, idsz; ssize_t wt, rd; int cnt, sent, rcvd; float mstot, avg; cnt = 1; sent = 0; rcvd = 0; mstot = 0.0; avg = 0.0; buflen = 2048; idsz = sizeof(neticmp_h) + sizeof(icmp_ts); CircularBuffer * rbuff = new CircularBuffer(buflen); wbuff = (char*) ::malloc(buflen); req = (neticmp_h*) wbuff; its = (icmp_ts*) wbuff + sizeof(neticmp_h); data = wbuff + idsz; req->type = ICMP_ECHO; req->code = 0; req->chksum = 0; req->id = Pid; req->seq = 0; if ( count > 0 ) cnt = count; if ( size > (buflen - idsz) ) size = buflen - idsz - 4; size += Serializer::PadLen(size); InitDataBlock(size); dt = RandData.substr(0, size).data(); ::memcpy(data, dt, size); its->size = size; std::cout << "Sending "; if ( count > 0 ) std::cout << "(" << count << ") " ; std::cout << "ICMP echo requests to " << IpAddr::ntop(dstaddr) << " (" << host << ")" << std::endl; std::cout << "ICMP data size is " << size << std::endl; while ( ! Alarm ) { rbuff->reset(); if ( ! getTimeOfDay(tvin) ) errorOut("error in gettime"); float lastsnt = timeDiff(tvin, tvsnt); if ( lastsnt >= interval ) sendReq = true; if ( sendReq && cnt > 0 ) { sz = idsz + size; // account for added data size tvsnt = tvin; its->secs = tvin.tv_sec; its->usecs = tvin.tv_usec; req->chksum = 0; req->seq++; req->chksum = Socket::IpChkSum((uint16_t*)req, sz); wt = icmps->write(wbuff, sz); if ( wt < 0 ) errorOut("Error in write " + icmps->getErrorString()); sent++; sendReq = false; if ( count > 0 ) cnt--; if ( debug ) std::cout << "Request <" << sent << "> sent" << std::endl; } sz = rbuff->writePtrAvailable(); wptr = rbuff->getWritePtr(&sz); if ( wptr == NULL ) errorOut("Error in writing to rbuff"); rd = icmps->readFrom(wptr, sz, csock); if ( rd < 0 ) errorOut("Error in readFrom " + icmps->getErrorString()); sa = (sockaddr_in*) &csock; addr = sa->sin_addr.s_addr; rbuff->setWritePtr(rd); if ( rd > 0 && addr == dstaddr ) { IcmpResponse response; if ( ! getTimeOfDay(tvin) ) errorOut("error in gettime"); rd = readIcmpHeader(rbuff, response); if ( rd > 0 && response.icmph.id == Pid ) { sz = rbuff->readAvailable(); rcvd++; if ( sz == sizeof(icmp_ts) ) { timeval tv; char * idf = rbuff->getReadPtr(&sz); icmp_ts * ist = (icmp_ts*) idf; tv.tv_sec = ist->secs; tv.tv_usec = ist->usecs; if ( debug ) std::cout << " Received data field in echo response" << std::endl; rbuff->setReadPtr(sz); } float ms = timeDiff(tvin, tvsnt); std::cout << (rd+sz) << " bytes from " << IpAddr::ntop(addr) << ": seq=" << response.icmph.seq << " time=" << ms << " ms" << std::endl; mstot += ms; avg = (float) mstot / rcvd; if ( debug ) std::cout << " mstot=" << mstot << " rcvd = " << rcvd << std::endl; } } if ( cnt == 0 ) { if ( rcvd == cnt ) break; if ( tvo.tv_sec == 0 ) tvo.tv_sec = tvin.tv_sec; else if ( (tvin.tv_sec - tvo.tv_sec) > timeout ) break; } ::usleep(1000); } float loss; if ( rcvd == sent ) loss = 0.0; else loss = ( 100.0 - ( ((float) rcvd / (float) sent) * 100.0) ); std::cout << std::endl << "Results:" << std::endl; std::cout << " Sent " << sent << " requests, received " << rcvd << ": Loss=" << loss << "% : Avg Time= " << avg << " ms " << std::endl; return 0; }
int main ( int argc, char ** argv ) { size_t buffsize = DEFAULT_CIRBUFFER_SIZE; size_t maxsize = MAX_CIRBUFFER_SIZE; if ( argc == 2 ) buffsize = StringUtils::FromString<size_t>(argv[1]); CircularBuffer * buff = new CircularBuffer(buffsize); std::string bstr = "0123456789"; int count = buffsize / bstr.length(); std::cout << " buffer capacity = " << buff->size() << ", max is " << maxsize << ", string '" << bstr << std::endl << "', count is " << count << std::endl << std::endl; while ( buff->writeAvailable() >= bstr.length() ) buff->write(bstr.c_str(), bstr.length()); char * out = (char*) calloc(bstr.length(), sizeof(char)); std::cout << " dataAvail in buffer = " << buff->readAvailable() << std::endl; for ( int i = 0; i < (count / 2); ++i ) { buff->read(out, bstr.length()); } std::cout << " read: '" << out << "'" << std::endl; buffsize = buffsize - (count / 2); std::cout << " resizing to " << buffsize << std::endl; if ( ! buff->resize(buffsize) ) std::cout << "RESIZE FAILED" << std::endl; std::cout << " buffer capacity = " << buff->size() << std::endl << " fullDataAvail = " << buff->readAvailable() << " dataAvail = " << buff->readPtrAvailable() << std::endl << " fullSpaceAvail = " << buff->writeAvailable() << " spaceAvail = " << buff->writePtrAvailable() << std::endl << std::endl; int c = 0; while ( buff->writePtrAvailable() >= bstr.length() ) { buff->write(bstr.c_str(), bstr.length()); c++; } std::cout << " write count = " << c << std::endl << std::endl; std::cout << " buffer capacity = " << buff->size() << std::endl << " fullDataAvail = " << buff->readAvailable() << " dataAvail = " << buff->readPtrAvailable() << std::endl << " fullSpaceAvail = " << buff->writeAvailable() << " spaceAvail = " << buff->writePtrAvailable() << std::endl << std::endl; buffsize = buff->size() + bstr.length(); std::cout << " resizing to " << buffsize << std::endl; if ( ! buff->resize(buffsize) ) std::cout << " RESIZE FAILED " << std::endl; std::cout << " buffer capacity = " << buff->size() << std::endl << " fullDataAvail = " << buff->readAvailable() << " dataAvail = " << buff->readPtrAvailable() << std::endl << " fullSpaceAvail = " << buff->writeAvailable() << " spaceAvail = " << buff->writePtrAvailable() << std::endl << std::endl; ::free(out); delete buff; return 0; }