From 68074cb22a3a0492cb31e3329a88e490944808fa Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 1 Aug 2014 12:59:10 -0700 Subject: [PATCH] added a simple udp send/receive jitter test tool --- tests/jitter/CMakeLists.txt | 33 +++++++++ tests/jitter/src/main.cpp | 139 ++++++++++++++++++++++++++++++++++++ 2 files changed, 172 insertions(+) create mode 100644 tests/jitter/CMakeLists.txt create mode 100644 tests/jitter/src/main.cpp diff --git a/tests/jitter/CMakeLists.txt b/tests/jitter/CMakeLists.txt new file mode 100644 index 0000000000..8000e4af50 --- /dev/null +++ b/tests/jitter/CMakeLists.txt @@ -0,0 +1,33 @@ +set(TARGET_NAME jitter-tests) + +set(ROOT_DIR ../..) +set(MACRO_DIR ${ROOT_DIR}/cmake/macros) + +# setup for find modules +set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/../../cmake/modules/") + +#find_package(Qt5Network REQUIRED) +#find_package(Qt5Script REQUIRED) +#find_package(Qt5Widgets REQUIRED) + +include(${MACRO_DIR}/SetupHifiProject.cmake) +setup_hifi_project(${TARGET_NAME} TRUE) + +#include(${MACRO_DIR}/AutoMTC.cmake) +#auto_mtc(${TARGET_NAME} ${ROOT_DIR}) + +#qt5_use_modules(${TARGET_NAME} Network Script Widgets) + +#include glm - because it's a dependency of shared utils... +include(${MACRO_DIR}/IncludeGLM.cmake) +include_glm(${TARGET_NAME} ${ROOT_DIR}) + +# link in the shared libraries +include(${MACRO_DIR}/LinkHifiLibrary.cmake) +link_hifi_library(shared ${TARGET_NAME} ${ROOT_DIR}) +link_hifi_library(networking ${TARGET_NAME} ${ROOT_DIR}) + +IF (WIN32) + target_link_libraries(${TARGET_NAME} Winmm Ws2_32) +ENDIF(WIN32) + diff --git a/tests/jitter/src/main.cpp b/tests/jitter/src/main.cpp new file mode 100644 index 0000000000..05a05e53d2 --- /dev/null +++ b/tests/jitter/src/main.cpp @@ -0,0 +1,139 @@ +// +// main.cpp +// JitterTester +// +// Created by Philip on 8/1/14. +// Copyright (c) 2014 High Fidelity, Inc. All rights reserved. +// + +#include +#include +#include +#include +#include +#include + +#include // for usecTimeStampNow() +#include // for MovingMinMaxAvg + +void runSend(const char* addressOption, int port, int gap, int size); +void runReceive(const char* addressOption, int port, int gap, int size); + + +int main(int argc, const char * argv[]) { + if (argc != 6) { + printf("usage: jitter-tests <--send|--receive>
\n"); + exit(1); + } + const char* typeOption = argv[1]; + const char* addressOption = argv[2]; + const char* portOption = argv[3]; + const char* gapOption = argv[4]; + const char* sizeOption = argv[5]; + int port = atoi(portOption); + int gap = atoi(gapOption); + int size = atoi(sizeOption); + + std::cout << "type:" << typeOption << "\n"; + std::cout << "address:" << addressOption << "\n"; + std::cout << "port:" << port << "\n"; + std::cout << "gap:" << gap << "\n"; + std::cout << "size:" << size << "\n"; + + if (strcmp(typeOption, "--send") == 0) { + runSend(addressOption, port, gap, size); + } else if (strcmp(typeOption, "--receive") == 0) { + runReceive(addressOption, port, gap, size); + } + exit(1); +} + +void runSend(const char* addressOption, int port, int gap, int size) { + std::cout << "runSend...\n"; + + int sockfd; + struct sockaddr_in servaddr; + + char* outputBuffer = new char[size]; + memset(outputBuffer, 0, size); + + sockfd=socket(AF_INET,SOCK_DGRAM,0); + + bzero(&servaddr,sizeof(servaddr)); + servaddr.sin_family = AF_INET; + servaddr.sin_addr.s_addr=inet_addr(addressOption); + servaddr.sin_port=htons(port); + + const int SAMPLES_FOR_30_SECONDS = 30 * 1000 / gap; + MovingMinMaxAvg timeGaps(1, SAMPLES_FOR_30_SECONDS); // stats + + quint64 last = usecTimestampNow(); + + while (true) { + + quint64 now = usecTimestampNow(); + quint64 actualGap = now - last; + + + if (actualGap >= gap) { + sendto(sockfd, outputBuffer, size, 0, (struct sockaddr *)&servaddr, sizeof(servaddr)); + + timeGaps.update(actualGap); + std::cout << "packet sent gap:" << actualGap << " " + << "min:" << timeGaps.getMin() << " " + << "max:" << timeGaps.getMax() << " " + << "avg:" << timeGaps.getAverage() << " " + << "min last 30:" << timeGaps.getWindowMin() << " " + << "max last 30:" << timeGaps.getWindowMax() << " " + << "avg last 30:" << timeGaps.getWindowAverage() << " " + << "\n"; + last = now; + } + } +} + +void runReceive(const char* addressOption, int port, int gap, int size) { + std::cout << "runReceive...\n"; + + + int sockfd,n; + struct sockaddr_in myaddr; + + char* inputBuffer = new char[size]; + memset(inputBuffer, 0, size); + + sockfd=socket(AF_INET, SOCK_DGRAM, 0); + + bzero(&myaddr,sizeof(myaddr)); + myaddr.sin_family = AF_INET; + myaddr.sin_addr.s_addr=htonl(INADDR_ANY); + myaddr.sin_port=htons(port); + + const int SAMPLES_FOR_30_SECONDS = 30 * 1000 / gap; + MovingMinMaxAvg timeGaps(1, SAMPLES_FOR_30_SECONDS); // stats + + if (bind(sockfd, (struct sockaddr *)&myaddr, sizeof(myaddr)) < 0) { + std::cout << "bind failed\n"; + return; + } + + quint64 last = usecTimestampNow(); + + while (true) { + n = recvfrom(sockfd, inputBuffer, size, 0, NULL, NULL); // we don't care about where it came from + + quint64 now = usecTimestampNow(); + int actualGap = now - last; + timeGaps.update(actualGap); + std::cout << "packet received gap:" << actualGap << " " + << "min:" << timeGaps.getMin() << " " + << "max:" << timeGaps.getMax() << " " + << "avg:" << timeGaps.getAverage() << " " + << "min last 30:" << timeGaps.getWindowMin() << " " + << "max last 30:" << timeGaps.getWindowMax() << " " + << "avg last 30:" << timeGaps.getWindowAverage() << " " + << "\n"; + last = now; + } +} +