summaryrefslogtreecommitdiffstats
path: root/lib/libUPnP/Neptune/Source/Apps/NetBench/NetBench.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libUPnP/Neptune/Source/Apps/NetBench/NetBench.cpp')
-rw-r--r--lib/libUPnP/Neptune/Source/Apps/NetBench/NetBench.cpp256
1 files changed, 256 insertions, 0 deletions
diff --git a/lib/libUPnP/Neptune/Source/Apps/NetBench/NetBench.cpp b/lib/libUPnP/Neptune/Source/Apps/NetBench/NetBench.cpp
new file mode 100644
index 0000000..29d876a
--- /dev/null
+++ b/lib/libUPnP/Neptune/Source/Apps/NetBench/NetBench.cpp
@@ -0,0 +1,256 @@
+/*****************************************************************
+|
+| Neptune Utilities - Network Benchmark utility
+|
+| (c) 2001-2013 Gilles Boccon-Gibod
+| Author: Gilles Boccon-Gibod (bok@bok.net)
+|
+ ****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "Neptune.h"
+#include <stdio.h>
+
+/*----------------------------------------------------------------------
+| Config
++---------------------------------------------------------------------*/
+const unsigned int STATS_WINDOW_SIZE = 100;
+
+/*----------------------------------------------------------------------
+| PrintUsageAndExit
++---------------------------------------------------------------------*/
+static void
+PrintUsageAndExit(void)
+{
+ fprintf(stderr,
+ "NetBench [options] <url>\n"
+ "\n"
+ " Options:\n"
+ " --threads <n> : use <n> independent threads for requests\n"
+ " --max-requests <n> : stop after <n> requests\n"
+ " --max-time <n> : stop after <n> seconds\n"
+ " --ssl-client-cert <filename> : load client TLS certificate from <filename> (PKCS12)\n"
+ " --ssl-client-cert-password <password> : optional password for the client cert\n"
+ );
+}
+
+/*----------------------------------------------------------------------
+| Worker
++---------------------------------------------------------------------*/
+class Worker : public NPT_Thread
+{
+public:
+ Worker(const char* url,
+ NPT_TlsContext* tls_context,
+ unsigned int tls_options) :
+ m_Url(url),
+ m_Connector(NULL),
+ m_Iterations(0),
+ m_Failures(0),
+ m_Done(false),
+ m_ShouldStop(false)
+ {
+ if (tls_context) {
+ m_Connector = new NPT_HttpTlsConnector(*tls_context, tls_options);
+ m_Client.SetConnector(m_Connector);
+ }
+ }
+
+ ~Worker() {
+ delete m_Connector;
+ }
+
+ void Run() {
+ // get the document
+ NPT_HttpRequest request(m_Url, NPT_HTTP_METHOD_GET);
+
+ while (!m_ShouldStop) {
+ NPT_HttpResponse* response = NULL;
+
+ NPT_Result result = m_Client.SendRequest(request, response);
+ if (NPT_FAILED(result)) {
+ ++m_Failures;
+ continue;
+ }
+
+ // load body
+ NPT_HttpEntity* entity = response->GetEntity();
+ if (entity != NULL) {
+ NPT_DataBuffer body;
+ result = entity->Load(body);
+ if (NPT_FAILED(result)) {
+ ++m_Failures;
+ continue;
+ }
+ }
+
+ ++m_Iterations;
+ delete response;
+ }
+ }
+
+ NPT_HttpUrl m_Url;
+ NPT_HttpClient m_Client;
+ NPT_HttpClient::Connector* m_Connector;
+ NPT_UInt32 m_Iterations;
+ NPT_UInt32 m_Failures;
+ volatile bool m_Done;
+ volatile bool m_ShouldStop;
+};
+
+/*----------------------------------------------------------------------
+| main
++---------------------------------------------------------------------*/
+int
+main(int argc, char** argv)
+{
+ // check command line
+ if (argc < 2) {
+ PrintUsageAndExit();
+ return 1;
+ }
+
+ // init options
+#if defined(NPT_CONFIG_ENABLE_TLS)
+ unsigned int tls_options = NPT_HttpTlsConnector::OPTION_ACCEPT_SELF_SIGNED_CERTS | NPT_HttpTlsConnector::OPTION_ACCEPT_HOSTNAME_MISMATCH;
+#else
+ unsigned int tls_options = 0;
+#endif
+ const char* tls_cert_filename = NULL;
+ const char* tls_cert_password = NULL;
+ const char* url = NULL;
+ unsigned int threads = 1;
+ unsigned int max_requests = 0;
+ unsigned int max_time = 0;
+
+ // parse command line
+ ++argv;
+ const char* arg;
+ while ((arg = *argv++)) {
+ if (NPT_StringsEqual(arg, "--threads")) {
+ NPT_ParseInteger(*argv++, threads);
+ if (threads < 1) threads = 1;
+ } else if (NPT_StringsEqual(arg, "--max-requests")) {
+ NPT_ParseInteger(*argv++, max_requests);
+ } else if (NPT_StringsEqual(arg, "--max-time")) {
+ NPT_ParseInteger(*argv++, max_time);
+ } else if (NPT_StringsEqual(arg, "--ssl-client-cert")) {
+ tls_cert_filename = *argv++;
+ if (tls_cert_filename == NULL) {
+ fprintf(stderr, "ERROR: missing argument after --ssl-client-cert option\n");
+ return 1;
+ }
+ } else if (NPT_StringsEqual(arg, "--ssl-client-cert-password")) {
+ tls_cert_password = *argv++;
+ if (tls_cert_password == NULL) {
+ fprintf(stderr, "ERROR: missing argument after --ssl-client-cert-password option\n");
+ return 1;
+ }
+ } else if (url == NULL) {
+ url = arg;
+ } else {
+ fprintf(stderr, "ERROR: unexpected argument '%s'\n", arg);
+ return 1;
+ }
+ }
+
+ // load a client cert if needed
+ NPT_TlsContext* tls_context = NULL;
+#if defined(NPT_CONFIG_ENABLE_TLS)
+ if (tls_options || tls_cert_filename) {
+ tls_context = new NPT_TlsContext(NPT_TlsContext::OPTION_VERIFY_LATER | NPT_TlsContext::OPTION_ADD_DEFAULT_TRUST_ANCHORS/* | NPT_TlsContext::OPTION_NO_SESSION_CACHE*/);
+ if (tls_cert_filename) {
+ NPT_DataBuffer cert;
+ NPT_Result result = NPT_File::Load(tls_cert_filename, cert);
+ if (NPT_FAILED(result)) {
+ fprintf(stderr, "ERROR: failed to load client cert from file %s (%d)\n", tls_cert_filename, result);
+ return 1;
+ }
+ result = tls_context->LoadKey(NPT_TLS_KEY_FORMAT_PKCS12, cert.GetData(), cert.GetDataSize(), tls_cert_password);
+ if (NPT_FAILED(result)) {
+ fprintf(stderr, "ERROR: failed to parse client cert (%d)\n", result);
+ return 1;
+ }
+ }
+ }
+#endif
+
+ NPT_Array<Worker*> workers;
+ for (unsigned int i=0; i<threads; i++) {
+ Worker* worker = new Worker(url, tls_context, tls_options);
+ workers.Add(worker);
+ worker->Start();
+ }
+
+ NPT_TimeStamp start_time;
+ NPT_System::GetCurrentTimeStamp(start_time);
+
+ struct {
+ unsigned int request_count;
+ unsigned int failure_count;
+ NPT_TimeStamp timestamp;
+ } stats[STATS_WINDOW_SIZE];
+ unsigned int cursor = 0;
+ for (unsigned int loop = 0; true; loop++) {
+ unsigned int total_requests = 0;
+ unsigned int total_failures = 0;
+ bool all_done = true;
+ for (unsigned int i=0; i<threads; i++) {
+ total_requests += workers[i]->m_Iterations;
+ total_failures += workers[i]->m_Failures;
+ if (!workers[i]->m_Done) all_done = false;
+ }
+ NPT_TimeStamp now;
+ NPT_System::GetCurrentTimeStamp(now);
+ stats[cursor].timestamp = now;
+ stats[cursor].request_count = total_requests;
+ stats[cursor].failure_count = total_failures;
+
+ int newest = cursor;
+ int oldest = (cursor+1)%STATS_WINDOW_SIZE;
+ if (loop < STATS_WINDOW_SIZE) {
+ oldest = 0;
+ }
+ unsigned int reqs_in_window = stats[newest].request_count - stats[oldest].request_count;
+ NPT_TimeStamp window_duration = stats[newest].timestamp - stats[oldest].timestamp;
+ double rate = 0.0;
+ if (window_duration.ToMillis()) {
+ rate = 1000.0*(double)reqs_in_window/(double)window_duration.ToMillis();
+ }
+ printf("\rReqs: %d - Fail: %d - Rate: %.2f tps", total_requests, total_failures, (float)rate);
+ fflush(stdout);
+
+ cursor = (cursor+1)%STATS_WINDOW_SIZE;
+
+ if (max_time && (now-start_time).ToSeconds() >= max_time) {
+ break;
+ }
+ if (max_requests && total_requests >= max_requests) {
+ break;
+ }
+ if (all_done) {
+ break;
+ }
+ NPT_System::Sleep(0.1);
+ }
+ printf("\n");
+
+ for (unsigned int i=0; i<threads; i++) {
+ workers[i]->m_ShouldStop = true;
+ }
+
+ for (unsigned int i=0; i<threads; i++) {
+ workers[i]->Wait();
+ delete workers[i];
+ }
+
+ delete tls_context;
+
+ return 0;
+}
+
+
+
+