summaryrefslogtreecommitdiff
path: root/src/Sockets/tests
diff options
context:
space:
mode:
Diffstat (limited to 'src/Sockets/tests')
-rw-r--r--src/Sockets/tests/Makefile73
-rw-r--r--src/Sockets/tests/base64.cpp34
-rw-r--r--src/Sockets/tests/copy.cpp264
-rw-r--r--src/Sockets/tests/crlf.cpp139
-rw-r--r--src/Sockets/tests/echoserver.cpp237
-rw-r--r--src/Sockets/tests/events.cpp212
-rw-r--r--src/Sockets/tests/http.cpp65
-rw-r--r--src/Sockets/tests/http_post.cpp107
-rw-r--r--src/Sockets/tests/httpd.cpp109
-rw-r--r--src/Sockets/tests/https.cpp113
-rw-r--r--src/Sockets/tests/resolve.cpp156
-rw-r--r--src/Sockets/tests/resume.cpp111
-rw-r--r--src/Sockets/tests/retry.cpp67
-rw-r--r--src/Sockets/tests/semtest.cpp96
-rw-r--r--src/Sockets/tests/sloppy_http.cpp55
-rw-r--r--src/Sockets/tests/sockets_test.cpp347
-rw-r--r--src/Sockets/tests/stressclient.cpp516
-rw-r--r--src/Sockets/tests/x.cpp298
18 files changed, 2999 insertions, 0 deletions
diff --git a/src/Sockets/tests/Makefile b/src/Sockets/tests/Makefile
new file mode 100644
index 0000000..0bbabf8
--- /dev/null
+++ b/src/Sockets/tests/Makefile
@@ -0,0 +1,73 @@
+SOCKETS = ..
+PLATFORM = linux-x86-32
+LIBS = -L$(SOCKETS) -lSockets
+
+INCLUDE = -I$(SOCKETS)
+include $(SOCKETS)/Makefile.version
+include $(SOCKETS)/Makefile.Defines.$(PLATFORM)
+
+CPPFLAGS = $(CFLAGS)
+
+#LIBS += -lsctp
+
+PROGS = events resolve sockets_test base64 semtest \
+ echoserver stressclient http httpd retry resume \
+ http_post x copy crlf https sloppy_http
+
+all: $(PROGS)
+
+events: events.o
+ $(CXX) -o $@ $^ $(LIBS)
+
+resolve: resolve.o
+ $(CXX) -o $@ $^ $(LIBS)
+
+sockets_test: sockets_test.o
+ $(CXX) -o $@ $^ $(LIBS)
+
+base64: base64.o
+ $(CXX) -o $@ $^ $(LIBS)
+
+semtest: semtest.o
+ $(CXX) -o $@ $^ $(LIBS)
+
+echoserver: echoserver.o
+ $(CXX) -o $@ $^ $(LIBS)
+
+stressclient: stressclient.o
+ $(CXX) -o $@ $^ $(LIBS)
+
+http: http.o
+ $(CXX) -o $@ $^ $(LIBS)
+
+httpd: httpd.o
+ $(CXX) -o $@ $^ $(LIBS)
+
+retry: retry.o
+ $(CXX) -o $@ $^ $(LIBS)
+
+resume: resume.o
+ $(CXX) -o $@ $^ $(LIBS)
+
+http_post: http_post.o
+ $(CXX) -o $@ $^ $(LIBS)
+
+x: x.o
+ $(CXX) -o $@ $^ $(LIBS)
+
+copy: copy.o
+ $(CXX) -o $@ $^ $(LIBS)
+
+crlf: crlf.o
+ $(CXX) -o $@ $^ $(LIBS)
+
+https: https.o
+ $(CXX) -o $@ $^ $(LIBS)
+
+sloppy_http: sloppy_http.o
+ $(CXX) -o $@ $^ $(LIBS)
+
+clean:
+ rm -f *.o *~ slask *.d $(PROGS)
+
+-include *.d
diff --git a/src/Sockets/tests/base64.cpp b/src/Sockets/tests/base64.cpp
new file mode 100644
index 0000000..722439d
--- /dev/null
+++ b/src/Sockets/tests/base64.cpp
@@ -0,0 +1,34 @@
+#include <stdio.h>
+
+#include "Base64.h"
+
+
+int main(int argc,char *argv[])
+{
+ if (argc < 2)
+ return -1;
+ std::string str;
+ std::string str2;
+ Base64 b;
+ if (!strcmp(argv[1],"-file"))
+ {
+ if (argc < 3)
+ return -2;
+ FILE *fil;
+ if ((fil = fopen(argv[2],"rt")) != NULL)
+ {
+ b.encode(fil, str);
+ fclose(fil);
+ }
+ printf("File:\n%s\n--End of File\n",str.c_str());
+ b.decode(str, str2);
+ printf("Content:\n%s\n--End of Content\n",str2.c_str());
+ }
+ else
+ {
+ b.encode(argv[1], strlen(argv[1]), str);
+ printf("'%s' ==> '%s'",argv[1], str.c_str());
+ b.decode(str, str2);
+ printf(" ==> '%s'\n",str2.c_str());
+ }
+}
diff --git a/src/Sockets/tests/copy.cpp b/src/Sockets/tests/copy.cpp
new file mode 100644
index 0000000..2134ac2
--- /dev/null
+++ b/src/Sockets/tests/copy.cpp
@@ -0,0 +1,264 @@
+#include <TcpSocket.h>
+#include <SocketHandler.h>
+#include <ListenSocket.h>
+#include <Utility.h>
+
+#define BUFSZ 7024
+
+#ifdef _WIN32
+#define MIN(a,b) (a<b?a:b)
+
+#endif
+
+static int quit = 0;
+static size_t lim = 120000;
+
+
+class CopySocket : public TcpSocket
+{
+public:
+ CopySocket(ISocketHandler& h) : TcpSocket(h), m_fil(NULL), m_out(NULL), m_b_server(false), m_sz(0) {
+ SetTransferLimit(60000);
+ }
+ CopySocket(ISocketHandler& h, size_t sz) : TcpSocket(h), m_fil(NULL), m_out(NULL), m_b_server(false), m_sz(sz) {
+ SetTransferLimit(60000);
+ quit++;
+ }
+ CopySocket(ISocketHandler& h, const std::string& filename) : TcpSocket(h), m_filename(filename), m_fil(NULL), m_out(NULL), m_b_server(false), m_sz(0) {
+ SetTransferLimit(60000);
+ quit++;
+ }
+ ~CopySocket() {
+ quit--;
+ }
+
+ void OnConnect() {
+ Utility::GetTime(&m_start);
+ if (!m_filename.size())
+ {
+ Send("\n");
+ char buf[BUFSZ];
+ int n = MIN(m_sz, BUFSZ);
+ while (n > 0 && GetOutputLength() < lim)
+ {
+ SendBuf(buf, n);
+ m_sz -= n;
+ n = MIN(m_sz, BUFSZ);
+ }
+ if (!n)
+ {
+ SetCloseAndDelete();
+ }
+ else
+ {
+ SendBuf(buf, n);
+ m_sz -= n;
+ }
+ return;
+ }
+ size_t x = 0;
+ for (size_t i = 0; i < m_filename.size(); i++)
+ if (m_filename[i] == '/')
+ x = i + 1;
+ Send(m_filename.substr(x) + "\n");
+ m_fil = fopen(m_filename.c_str(), "rb");
+ if (m_fil)
+ {
+ char buf[BUFSZ];
+ int n = fread(buf, 1, BUFSZ, m_fil);
+ while (n > 0 && GetOutputLength() < lim)
+ {
+ SendBuf(buf, n);
+ n = fread(buf, 1, BUFSZ, m_fil);
+ }
+ if (!n)
+ {
+ SetCloseAndDelete();
+ fclose(m_fil);
+ m_fil = NULL;
+ }
+ else
+ {
+ SendBuf(buf, n);
+ }
+ }
+ }
+
+ void OnWriteComplete() {
+ }
+
+ void OnTransferLimit() {
+ if (!m_filename.size())
+ {
+ char buf[BUFSZ];
+ int n = MIN(m_sz, BUFSZ);
+ while (n > 0 && GetOutputLength() < lim)
+ {
+ SendBuf(buf, n);
+ m_sz -= n;
+ n = MIN(m_sz, BUFSZ);
+ }
+ if (!n)
+ {
+ SetCloseAndDelete();
+ }
+ else
+ {
+ SendBuf(buf, n);
+ m_sz -= n;
+ }
+ return;
+ }
+ if (m_fil)
+ {
+ char buf[BUFSZ];
+ int n = fread(buf, 1, BUFSZ, m_fil);
+ while (n > 0 && GetOutputLength() < lim)
+ {
+ SendBuf(buf, n);
+ n = fread(buf, 1, BUFSZ, m_fil);
+ }
+ if (!n)
+ {
+ SetCloseAndDelete();
+ fclose(m_fil);
+ m_fil = NULL;
+ }
+ else
+ {
+ SendBuf(buf, n);
+ }
+ }
+ }
+
+ void OnAccept() {
+ Utility::GetTime(&m_start);
+ m_b_server = true;
+ SetLineProtocol();
+ DisableInputBuffer();
+ }
+
+ void OnLine(const std::string& line) {
+ if (line.size())
+ m_out = fopen(line.c_str(), "wb");
+ SetLineProtocol(false);
+ DisableInputBuffer();
+ }
+
+ void OnDelete() {
+ struct timeval stop;
+ Utility::GetTime(&stop);
+ stop.tv_sec -= m_start.tv_sec;
+ stop.tv_usec -= m_start.tv_usec;
+ if (stop.tv_usec < 0)
+ {
+ stop.tv_usec += 1000000;
+ stop.tv_sec -= 1;
+ }
+ double t = stop.tv_usec;
+ t /= 1000000;
+ t += stop.tv_sec;
+ printf("OnDelete: %s\n", m_b_server ? "SERVER" : "CLIENT");
+ printf(" Time: %ld.%06ld (%f)\n", stop.tv_sec, stop.tv_usec, t);
+ double r = GetBytesReceived();
+ printf(" bytes in: %lld (%f Mbytes/sec)\n", GetBytesReceived(), r / t / 1000000);
+ double s = GetBytesSent();
+ printf(" bytes out: %lld (%f Mbytes/sec)\n", GetBytesSent(), s / t / 1000000);
+ printf("\n");
+ if (m_out)
+ fclose(m_out);
+ }
+
+ void OnRawData(const char *buf, size_t len) {
+ if (m_out)
+ fwrite(buf, 1, len, m_out);
+ }
+
+private:
+ std::string m_filename;
+ FILE *m_fil;
+ FILE *m_out;
+ bool m_b_server;
+ struct timeval m_start;
+ size_t m_sz;
+};
+
+
+int main(int argc, char *argv[])
+{
+ std::string host = "127.0.0.1";
+ int port = 12344;
+ std::list<std::string> filenames;
+
+ for (int i = 1; i < argc; i++)
+ {
+ if (!strcmp(argv[i], "-host") && i < argc - 1)
+ host = argv[++i];
+ else
+ if (!strcmp(argv[i], "-port") && i < argc - 1)
+ port = atoi(argv[++i]);
+ else
+ if (!strcmp(argv[i], "-h"))
+ {
+ fprintf(stderr, "Usage: %s [-host <host>] [-port <port>] [<file to send>]\n", *argv);
+ fprintf(stderr, " Will run as host only if <file to send> isn't specified.\n");
+ fprintf(stderr, " host default: 127.0.0.1\n");
+ fprintf(stderr, " port default: 12344\n");
+ return 0;
+ }
+ else
+ {
+ filenames.push_back( argv[i] );
+ }
+ }
+
+ try
+ {
+ SocketHandler h;
+ ListenSocket<CopySocket> l(h);
+ if (filenames.empty())
+ {
+ if (l.Bind( port ) != 0)
+ {
+ fprintf(stderr, "Bind() port %d failed - exiting\n", port);
+ return -1;
+ }
+ h.Add(&l);
+ }
+ for (std::list<std::string>::iterator it = filenames.begin(); it != filenames.end(); it++)
+ {
+ std::string filename = *it;
+ size_t sz = atol(filename.c_str());
+ if (sz)
+ {
+ CopySocket *sock = new CopySocket(h, sz);
+ sock -> SetDeleteByHandler();
+ sock -> Open(host, port);
+ h.Add(sock);
+ }
+ else
+ {
+ CopySocket *sock = new CopySocket(h, filename);
+ sock -> SetDeleteByHandler();
+ sock -> Open(host, port);
+ h.Add(sock);
+ }
+ }
+ if (!filenames.size())
+ {
+ fprintf(stderr, "Starting as server only, listening on port %d\n", port);
+ quit++;
+ }
+ while (quit > 0)
+ {
+ h.Select(5, 0);
+ }
+ return 0;
+ }
+ catch (const Exception& e)
+ {
+ printf("%s\n", e.ToString().c_str());
+ }
+}
+
+
diff --git a/src/Sockets/tests/crlf.cpp b/src/Sockets/tests/crlf.cpp
new file mode 100644
index 0000000..34500c4
--- /dev/null
+++ b/src/Sockets/tests/crlf.cpp
@@ -0,0 +1,139 @@
+#include <TcpSocket.h>
+#include <SocketHandler.h>
+#include <ListenSocket.h>
+
+
+static bool quit = false;
+
+
+class IOSocket : public TcpSocket
+{
+public:
+ IOSocket(ISocketHandler& h) : TcpSocket(h) {
+ SetLineProtocol();
+ }
+ ~IOSocket() {}
+
+ void OnConnect() {
+ Utility::GetTime(&m_start);
+ while (GetOutputLength() < 500000)
+ {
+ Send("zzzzzzzzzmmmmmmmmm1234lkkk54\r\n");
+ Send("zzzzzzzzzmmmmmmmmm1234lkkk543\r\n");
+ Send("zzzzzzzzzmmmmmmmmm1234lkkk54\r\n");
+ Send("zzzzzzzzzmmmmmmmmm1234lkkk543\r\n");
+ Send("zzzzzzzzzmmmmmmmmm1234lkkk54\r\n");
+ Send("zzzzzzzzzmmmmmmmmm1234lkkk543\r\n");
+ Send("zzzzzzzzzmmmmmmmmm1234lkkk54\r\n");
+ Send("zzzzzzzzzmmmmmmmmm1234lkkk543\r\n");
+ }
+// Send("\r\n");
+ }
+
+ void OnAccept() {
+ SetLineProtocol();
+ }
+
+ void OnDelete() {
+ printf("OnDelete\n");
+ }
+
+ void OnWriteComplete() {
+printf("OnWriteComplete\n");
+ struct timeval tv;
+ Utility::GetTime(&tv);
+
+ tv.tv_sec -= m_start.tv_sec;
+ tv.tv_usec -= m_start.tv_usec;
+ Utility::GetTime(&m_start);
+ if (tv.tv_usec < 0)
+ {
+ tv.tv_usec += 1000000;
+ tv.tv_sec -= 1;
+ }
+ double t = tv.tv_usec;
+ t /= 1000000;
+ t += tv.tv_sec;
+ printf(" Time: %ld.%06ld (%f)\n", tv.tv_sec, tv.tv_usec, t);
+ double r = GetBytesReceived();
+ printf(" bytes in: %lld (%f Mbytes/sec)\n", GetBytesReceived(true), r / t / 1000000);
+ double s = GetBytesSent();
+ printf(" bytes out: %lld (%f Mbytes/sec)\n", GetBytesSent(true), s / t / 1000000);
+ printf("\n");
+
+ while (GetOutputLength() < 500000)
+ {
+ Send("zzzzzzzzzmmmmmmmmm1234lkkk54\r\n");
+ Send("zzzzzzzzzmmmmmmmmm1234lkkk543\r\n");
+ Send("zzzzzzzzzmmmmmmmmm1234lkkk54\r\n");
+ Send("zzzzzzzzzmmmmmmmmm1234lkkk543\r\n");
+ Send("zzzzzzzzzmmmmmmmmm1234lkkk54\r\n");
+ Send("zzzzzzzzzmmmmmmmmm1234lkkk543\r\n");
+ Send("zzzzzzzzzmmmmmmmmm1234lkkk54\r\n");
+ Send("zzzzzzzzzmmmmmmmmm1234lkkk543\r\n");
+ }
+// Send("\r\n");
+ }
+
+ void OnLine(const std::string& line) {
+ if (line == "")
+ {
+ struct timeval tv;
+ Utility::GetTime(&tv);
+
+ tv.tv_sec -= m_start.tv_sec;
+ tv.tv_usec -= m_start.tv_usec;
+ Utility::GetTime(&m_start);
+ if (tv.tv_usec < 0)
+ {
+ tv.tv_usec += 1000000;
+ tv.tv_sec -= 1;
+ }
+ double t = tv.tv_usec;
+ t /= 1000000;
+ t += tv.tv_sec;
+ printf(" Time: %ld.%06ld (%f)\n", tv.tv_sec, tv.tv_usec, t);
+ double r = GetBytesReceived();
+ printf(" bytes in: %lld (%f Mbytes/sec)\n", GetBytesReceived(true), r / t / 1000000);
+ double s = GetBytesSent();
+ printf(" bytes out: %lld (%f Mbytes/sec)\n", GetBytesSent(true), s / t / 1000000);
+ printf("\n");
+
+ }
+ else
+ if (line != "zzzzzzzzzmmmmmmmmm1234lkkk54" &&
+ line != "zzzzzzzzzmmmmmmmmm1234lkkk543")
+ {
+printf("\n-------------------------------------------------------\n");
+ for (size_t i = 0; i < line.size(); i++)
+ if (!isprint(line[i]))
+ printf("<%d>", line[i]);
+ else
+ printf("%c", line[i]);
+ printf("\n");
+fflush(stdout);
+exit(-1);
+ quit = true;
+ }
+ }
+
+ struct timeval m_start;
+};
+
+
+int main(int argc, char *argv[])
+{
+ SocketHandler h;
+ ListenSocket<IOSocket> l(h);
+ l.Bind(12344);
+ h.Add(&l);
+ IOSocket sock(h);
+ sock.Open("192.168.7.4", 12344);
+ h.Add(&sock);
+ while (!quit)
+ {
+ h.Select(1, 0);
+ }
+}
+
+
diff --git a/src/Sockets/tests/echoserver.cpp b/src/Sockets/tests/echoserver.cpp
new file mode 100644
index 0000000..45cb6c2
--- /dev/null
+++ b/src/Sockets/tests/echoserver.cpp
@@ -0,0 +1,237 @@
+/**
+ ** \file echoserver.cpp
+ ** \date 2006-10-02
+ ** \author grymse@alhem.net
+**/
+/*
+Copyright (C) 2006 Anders Hedstrom
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+#ifdef _WIN32
+#pragma warning(disable:4786)
+#endif
+#include <StdoutLog.h>
+#include <ListenSocket.h>
+#include <SocketHandler.h>
+#include <TcpSocket.h>
+#ifndef _WIN32
+#include <signal.h>
+#endif
+#include <HttpDebugSocket.h>
+
+
+#ifdef ENABLE_DETACH
+static bool g_b_detach = false;
+#endif
+#ifdef HAVE_OPENSSL
+static bool g_b_ssl = false;
+#endif
+static std::string gFilename = "server.pem";
+static std::string gPw;
+static bool quit = false;
+static bool g_b_http = false;
+static bool g_b_nobuf = false;
+#ifdef ENABLE_DETACH
+static bool g_b_detach2 = false;
+#endif
+
+#define DEB(x)
+
+
+class MySocket : public TcpSocket
+{
+public:
+ MySocket(ISocketHandler& h) : TcpSocket(h) {
+ SetLineProtocol();
+#ifdef HAVE_OPENSSL
+ if (g_b_ssl)
+ EnableSSL();
+#endif
+ if (g_b_nobuf)
+ DisableInputBuffer();
+ }
+ ~MySocket() {
+ }
+
+ void OnAccept() {
+#ifdef ENABLE_DETACH
+ if (g_b_detach)
+ {
+ if (!Detach())
+ fprintf(stderr, "\nDetach failed\n");
+ }
+#endif
+ }
+
+ void OnRawData(const char *buf,size_t len) {
+ if (g_b_nobuf)
+ {
+ SendBuf(buf, len);
+ }
+ }
+
+ void OnLine(const std::string& line) {
+#ifdef ENABLE_DETACH
+ if (g_b_detach2 && !IsDetach())
+ {
+ m_line = line;
+ if (!Detach())
+ {
+ fprintf(stderr, "\nDetach failed\n");
+ }
+ return;
+ }
+DEB(printf("fd %d OnLine; %s\n", GetSocket(), Handler().IsSlave() ? "slave" : "master");)
+#endif
+ Send(line + "\n");
+ }
+
+ void OnDetached() {
+DEB(printf("fd %d OnDetached; %s\n", GetSocket(), Handler().IsSlave() ? "slave" : "master");)
+// fprintf(stderr, "-");
+// fflush(stderr);
+#ifdef ENABLE_DETACH
+ if (g_b_detach2)
+ {
+ Send(m_line + "\n");
+ }
+#endif
+ }
+
+#ifdef HAVE_OPENSSL
+ void InitSSLServer() {
+ InitializeContext("echoserver", gFilename, gPw, SSLv23_method());
+ }
+#endif
+
+private:
+ std::string m_line;
+};
+
+
+#ifndef _WIN32
+void sigint(int)
+{
+ quit = true;
+}
+#endif
+
+int main(int argc,char *argv[])
+{
+#ifndef _WIN32
+ signal(SIGPIPE, SIG_IGN);
+ signal(SIGINT, sigint);
+#endif
+ port_t port = 2222;
+ bool enableLog = false;
+ int queue = 20;
+ for (int i = 1; i < argc; i++)
+ {
+#ifdef ENABLE_DETACH
+ if (!strcmp(argv[i], "-detach"))
+ g_b_detach = true;
+ if (!strcmp(argv[i], "-detach2"))
+ g_b_detach2 = true;
+#endif
+#ifdef HAVE_OPENSSL
+ if (!strcmp(argv[i], "-ssl"))
+ g_b_ssl = true;
+ if (!strcmp(argv[i], "-file") && i < argc - 1)
+ gFilename = argv[++i];
+#endif
+ if (!strcmp(argv[i], "-port") && i < argc - 1)
+ port = atoi(argv[++i]);
+ if (!strcmp(argv[i], "-pw") && i < argc - 1)
+ gPw = argv[++i];
+ if (!strcmp(argv[i], "-log"))
+ enableLog = true;
+ if (!strcmp(argv[i], "-queue") && i < argc - 1)
+ queue = atoi(argv[++i]);
+ if (!strcmp(argv[i], "-http"))
+ g_b_http = true;
+ if (!strcmp(argv[i], "-nobuf"))
+ g_b_nobuf = true;
+ if (!strcmp(argv[i], "-h"))
+ {
+ printf("Usage: %s [ options ] [-ssl]\n", *argv);
+ printf(" -port nn listen on port nn\n");
+#ifdef ENABLE_DETACH
+ printf(" -detach detach each socket on accept\n");
+ printf(" -detach2 detach when line received\n");
+#endif
+#ifdef HAVE_OPENSSL
+ printf(" -ssl run as ssl server, .pem file needed\n");
+ printf(" -file xx .pem filename, default is \"server.pem\"\n");
+#endif
+ printf(" -pw xx private key password\n");
+ printf(" -log enable sockethandler debug log\n");
+ printf(" -queue nn listen queue size (default 20)\n");
+ printf(" -http enable http server with dummy response\n");
+ printf(" -nobuf echo raw data\n");
+ exit(-1);
+ }
+ }
+ if (g_b_http && g_b_nobuf)
+ {
+ printf("Nobuf and Http does not work together\n");
+ exit(-1);
+ }
+ StdoutLog *log = enableLog ? new StdoutLog() : NULL;
+ SocketHandler h(log);
+ ListenSocket<MySocket> l(h);
+ ListenSocket<HttpDebugSocket> l2(h);
+ if (!g_b_http)
+ {
+ if (l.Bind(port, queue))
+ {
+ fprintf(stderr, "Bind to port %d failed\n", port);
+ return -1;
+ }
+ fprintf(stderr, "Listening on port %d\n", port);
+ h.Add(&l);
+ }
+ else
+ {
+ printf("Enable HttpDebugSocket\n");
+ if (l2.Bind(port, queue))
+ {
+ fprintf(stderr, "Bind to port %d failed\n", port);
+ return -1;
+ }
+ fprintf(stderr, "Listening on port %d\n", port);
+ h.Add(&l2);
+ }
+#ifdef ENABLE_DETACH
+ if (g_b_detach)
+ fprintf(stderr, "Will detach each incoming socket\n");
+#endif
+#ifdef HAVE_OPENSSL
+ if (g_b_ssl)
+ fprintf(stderr, "Using SSL\n");
+#endif
+ while (!quit)
+ {
+ h.Select(1, 0);
+ }
+ fprintf(stderr, "\nExiting...\n");
+ if (log)
+ {
+// delete log;
+ }
+ return 0;
+}
+
+
diff --git a/src/Sockets/tests/events.cpp b/src/Sockets/tests/events.cpp
new file mode 100644
index 0000000..5d08973
--- /dev/null
+++ b/src/Sockets/tests/events.cpp
@@ -0,0 +1,212 @@
+#include <EventHandler.h>
+#include <TcpSocket.h>
+#include <IEventOwner.h>
+#include <ListenSocket.h>
+#include <StdoutLog.h>
+#include <iostream>
+
+
+double start;
+
+double gettime()
+{
+ struct timeval tv;
+ Utility::GetTime(&tv);
+ return tv.tv_sec + (double)tv.tv_usec / 1000000;
+}
+
+
+class MyEvHandler : public EventHandler
+{
+public:
+ MyEvHandler() : EventHandler() {}
+ MyEvHandler(StdLog *p) : EventHandler(p) {}
+
+};
+
+
+class EvThread : public Thread
+{
+public:
+ EvThread(Socket *p) : m_socket(p) {}
+
+ void Run();
+
+private:
+ Socket *m_socket;
+};
+
+
+class EvSocket : public TcpSocket, public IEventOwner
+{
+public:
+ EvSocket(ISocketHandler& h) : TcpSocket(h)
+ , IEventOwner( static_cast<MyEvHandler&>(h) ) {
+ }
+
+ void OnEvent(int id) {
+ std::cout << "OnEvent" << std::endl;
+ std::cout << gettime() - start << std::endl;
+ SetCloseAndDelete();
+ }
+
+ void OnAccept() {
+ std::cout << "Incoming" << std::endl;
+ }
+
+ void OnConnect() {
+ std::cout << "Connected" << std::endl;
+ EvThread *thr = new EvThread( this );
+ thr -> SetDeleteOnExit();
+ }
+
+ void OnDelete() {
+ std::cout << "EvSocket::OnDelete()" << std::endl;
+ }
+};
+
+
+void EvThread::Run()
+{
+ Socket *p0 = (Socket *)m_socket;
+ EvSocket *p = dynamic_cast<EvSocket *>(p0);
+ if (p)
+ {
+#ifdef _WIN32
+ Sleep( 5000 );
+#else
+ sleep(10);
+#endif
+ std::cout << "Add event" << std::endl;
+ start = gettime();
+ p -> AddEvent(1, 50000);
+ }
+ else
+ {
+ std::cout << "Thread: not an EvSocket" << std::endl;
+ }
+}
+
+
+//------------------------------------------------------------
+// myTimer class
+//------------------------------------------------------------
+class myTimer : public IEventOwner
+{
+public:
+ // Prototype of user call back function
+ typedef void (*myTimer_cb)(myTimer* user_func, void* user_id);
+
+ myTimer(IEventHandler& h, long ssec, long susec,
+ long psec, long pusec, myTimer_cb func, void* id);
+ ~myTimer();
+
+private:
+ void OnEvent(int id);
+ long ssec_;
+ long susec_;
+ long psec_;
+ long pusec_;
+ myTimer_cb user_func_;
+ void* user_id_;
+ bool periodic_;
+};
+
+
+//------------------------------------------------------------
+myTimer::myTimer(IEventHandler& h, long ssec, long susec,
+ long psec, long pusec, myTimer_cb user_func,
+ void* user_id) :
+ IEventOwner(h),
+ ssec_(ssec),
+ susec_(susec),
+ psec_(psec),
+ pusec_(pusec),
+ user_func_(user_func),
+ user_id_(user_id),
+ periodic_(psec != 0 || pusec != 0)
+{
+ AddEvent(ssec_, susec_);
+}
+
+
+//------------------------------------------------------------
+myTimer::~myTimer()
+{
+ ClearEvents();
+}
+
+
+//------------------------------------------------------------
+void myTimer::OnEvent(int id)
+{
+ if (periodic_)
+ {
+ int n = AddEvent(psec_, pusec_);
+ }
+
+ user_func_(this, user_id_);
+
+ if (!periodic_)
+ {
+ delete this;
+ }
+}
+
+
+//------------------------------------------------------------
+static void myfunc(myTimer* t, void* user_id)
+{
+ printf("Event %s\n", (char*)user_id);
+}
+
+
+/*
+int main(int argc, char *argv[])
+{
+ EventHandler h;
+
+ // Example 1: Create a 2 sec one-shot timer.
+ // No need to save the pointer as it will delete
+ // itself upon expiry.
+ new myTimer(h, 2, 0, 0, 0, myfunc, (void*)"My Timer 0");
+
+ // Example 2: Create a 1 sec periodic timer.
+ // Save the pointer because we can stop the timer
+ // later with a "delete mytimer".
+ myTimer* mytimer = new myTimer(h, 0, 0, 1, 0, myfunc,
+ (void*)"My Timer 1");
+
+ // Drop into the event handler ..
+ h.EventLoop();
+}
+*/
+
+
+int main(int argc, char *argv[])
+{
+ StdoutLog log;
+ MyEvHandler h(&log);
+ ListenSocket<EvSocket> l(h);
+ l.Bind("localhost", 12344);
+ h.Add(&l);
+
+ EvSocket sock(h);
+ sock.Open("localhost", 12344);
+ h.Add(&sock);
+
+ // Example 1: Create a 2 sec one-shot timer.
+ // No need to save the pointer as it will delete
+ // itself upon expiry.
+ new myTimer(h, 2, 0, 0, 0, myfunc, (void*)"My Timer 0");
+
+ // Example 2: Create a 1 sec periodic timer.
+ // Save the pointer because we can stop the timer
+ // later with a "delete mytimer".
+ myTimer* mytimer = new myTimer(h, 0, 0, 1, 0, myfunc,
+ (void*)"My Timer 1");
+
+ h.EventLoop();
+}
+
+
diff --git a/src/Sockets/tests/http.cpp b/src/Sockets/tests/http.cpp
new file mode 100644
index 0000000..6800699
--- /dev/null
+++ b/src/Sockets/tests/http.cpp
@@ -0,0 +1,65 @@
+#include <HTTPSocket.h>
+#include <SocketHandler.h>
+
+
+class tSocket : public HTTPSocket
+{
+public:
+ tSocket(ISocketHandler& h, const std::string& host) : HTTPSocket(h), m_host(host)
+ , m_first(false)
+ , m_sz(0) {
+ Open(host, 80);
+ }
+
+ void OnConnect() {
+ Send("GET /index.html HTTP/1.0\r\n");
+ Send("Host: " + m_host + "\r\n");
+ Send("\r\n");
+ }
+
+ void OnFirst() {
+ }
+
+ void OnHeader(const std::string& key, const std::string& value) {
+ fprintf(stderr, "%s: %s\n", key.c_str(), value.c_str());
+ }
+
+ void OnHeaderComplete() {
+ fprintf(stderr, "\n");
+ }
+
+ void OnData(const char *buf, size_t sz) {
+ if (1||!m_first)
+ {
+ std::string str = buf;
+ str.resize( sz );
+ printf("%s", str.c_str());
+ m_first = true;
+ }
+ m_sz += sz;
+ }
+
+ void OnDelete() {
+ fprintf(stderr, "Content length: %d\n", m_sz);
+ }
+
+private:
+ std::string m_host;
+ bool m_first;
+ size_t m_sz;
+};
+
+
+int main(int argc, char *argv[])
+{
+ std::string host = argc > 1 ? argv[1] : "www.alhem.net";
+ SocketHandler h;
+ tSocket sock(h, host);
+ h.Add(&sock);
+ while (h.GetCount())
+ {
+ h.Select(1, 0);
+ }
+}
+
+
diff --git a/src/Sockets/tests/http_post.cpp b/src/Sockets/tests/http_post.cpp
new file mode 100644
index 0000000..3b0b830
--- /dev/null
+++ b/src/Sockets/tests/http_post.cpp
@@ -0,0 +1,107 @@
+#include <HttpdSocket.h>
+#include <SocketHandler.h>
+#include <ListenSocket.h>
+#include <StdoutLog.h>
+#include <HttpPostSocket.h>
+#include <HttpPutSocket.h>
+#include <HttpdForm.h>
+
+
+class sSocket : public HttpdSocket
+{
+public:
+ sSocket(ISocketHandler& h) : HttpdSocket(h) {
+ }
+
+ void Init()
+ {
+ if (GetParent() -> GetPort() == 443 || GetParent() -> GetPort() == 8443)
+ {
+#ifdef HAVE_OPENSSL
+ EnableSSL();
+#else
+ fprintf(stderr, "SSL not available\n");
+#endif
+ }
+ }
+
+ void Exec()
+ {
+ std::string name;
+ std::string value;
+ GetForm() -> getfirst(name, value);
+ while (name.size())
+ {
+fprintf(stderr, "%s: '%s'\n", name.c_str(), value.c_str());
+ GetForm() -> getnext(name, value);
+ }
+ CreateHeader();
+ GenerateDocument();
+ }
+
+ void CreateHeader()
+ {
+ SetStatus("200");
+ SetStatusText("OK");
+fprintf(stderr, "Uri: '%s'\n", GetUri().c_str());
+ {
+ size_t x = 0;
+ for (size_t i = 0; i < GetUri().size(); i++)
+ if (GetUri()[i] == '.')
+ x = i;
+ std::string ext = GetUri().substr(x + 1);
+ if (ext == "gif" || ext == "jpg" || ext == "png")
+ AddResponseHeader("Content-type", "image/" + ext);
+ else
+ AddResponseHeader("Content-type", "text/" + ext);
+ }
+ AddResponseHeader("Connection", "close");
+ SendResponse();
+ }
+
+ void GenerateDocument()
+ {
+ Send("<html></html>");
+ SetCloseAndDelete();
+ }
+
+#ifdef HAVE_OPENSSL
+ void InitSSLServer()
+ {
+ InitializeContext("httpd", "comb.pem", "", SSLv23_method());
+ }
+#endif
+
+};
+
+
+int main(int argc, char *argv[])
+{
+ std::string host = argc > 1 ? argv[1] : "www.alhem.net";
+ StdoutLog log;
+ SocketHandler h(&log);
+ ListenSocket<sSocket> l(h);
+ if (l.Bind(1028))
+ {
+ printf("Bind port 1028 failed\n");
+ return -1;
+ }
+ h.Add(&l);
+ ListenSocket<sSocket> l2(h);
+ if (l2.Bind(8443))
+ {
+ printf("Bind port 8443 failed\n");
+ return -1;
+ }
+ h.Add(&l2);
+ HttpPostSocket sock(h, "http://localhost:1028/postdata");
+ sock.AddField("name", "value");
+ sock.Open();
+ h.Add(&sock);
+ while (h.GetCount())
+ {
+ h.Select(1, 0);
+ }
+}
+
+
diff --git a/src/Sockets/tests/httpd.cpp b/src/Sockets/tests/httpd.cpp
new file mode 100644
index 0000000..e1106a0
--- /dev/null
+++ b/src/Sockets/tests/httpd.cpp
@@ -0,0 +1,109 @@
+#include <HttpdSocket.h>
+#include <SocketHandler.h>
+#include <ListenSocket.h>
+#include <StdoutLog.h>
+
+
+class sSocket : public HttpdSocket
+{
+public:
+ sSocket(ISocketHandler& h) : HttpdSocket(h) {
+ }
+
+ void Init()
+ {
+ if (GetParent() -> GetPort() == 443 || GetParent() -> GetPort() == 8443)
+ {
+#ifdef HAVE_OPENSSL
+ EnableSSL();
+#else
+ fprintf(stderr, "SSL not available\n");
+#endif
+ }
+ }
+
+ void Exec()
+ {
+ CreateHeader();
+ GenerateDocument();
+ }
+
+ void CreateHeader()
+ {
+ SetStatus("200");
+ SetStatusText("OK");
+fprintf(stderr, "Uri: '%s'\n", GetUri().c_str());
+ {
+ size_t x = 0;
+ for (size_t i = 0; i < GetUri().size(); i++)
+ if (GetUri()[i] == '.')
+ x = i;
+ std::string ext = GetUri().substr(x + 1);
+ if (ext == "gif" || ext == "jpg" || ext == "png")
+ AddResponseHeader("Content-type", "image/" + ext);
+ else
+ AddResponseHeader("Content-type", "text/" + ext);
+ }
+ AddResponseHeader("Connection", "close");
+ SendResponse();
+ }
+
+ void GenerateDocument()
+ {
+ std::string fn = GetUri().substr(1);
+ FILE *fil = fopen(fn.c_str(), "rb");
+ if (fil)
+ {
+ char slask[1000];
+ int n = fread(slask,1,1000,fil);
+ while (n > 0)
+ {
+ SendBuf(slask, n);
+ n = fread(slask,1,1000,fil);
+ }
+ fclose(fil);
+ }
+ else
+ {
+ SetStatus("404");
+ SetStatusText("Not Found");
+ }
+ SetCloseAndDelete();
+ }
+
+#ifdef HAVE_OPENSSL
+ void InitSSLServer()
+ {
+ InitializeContext("httpd", "comb.pem", "", SSLv23_method());
+ }
+#endif
+
+};
+
+
+int main(int argc, char *argv[])
+{
+ std::string host = argc > 1 ? argv[1] : "www.alhem.net";
+ StdoutLog log;
+ SocketHandler h(&log);
+ ListenSocket<sSocket> l(h);
+ if (l.Bind(1028))
+ {
+ printf("Bind port 1028 failed\n");
+ return -1;
+ }
+ h.Add(&l);
+ ListenSocket<sSocket> l2(h);
+ if (l2.Bind(8443))
+ {
+ printf("Bind port 8443 failed\n");
+ return -1;
+ }
+ h.Add(&l2);
+ while (h.GetCount())
+ {
+ h.Select(1, 0);
+ }
+}
+
+
diff --git a/src/Sockets/tests/https.cpp b/src/Sockets/tests/https.cpp
new file mode 100644
index 0000000..45b36ff
--- /dev/null
+++ b/src/Sockets/tests/https.cpp
@@ -0,0 +1,113 @@
+#include <HTTPSocket.h>
+#include <SocketHandler.h>
+#include <ListenSocket.h>
+#include <Exception.h>
+
+
+class tSocket : public HTTPSocket
+{
+public:
+ tSocket(ISocketHandler& h) : HTTPSocket(h)
+ , m_first(false)
+ , m_sz(0) {
+ EnableSSL();
+ }
+
+ tSocket(ISocketHandler& h, const std::string& host) : HTTPSocket(h), m_host(host)
+ , m_first(false)
+ , m_sz(0) {
+ EnableSSL();
+ Open(host, 4443);
+ }
+
+ void InitSSLServer() {
+ InitializeContext("", "comb.pem", "", SSLv23_method());
+ }
+
+ void OnSSLAccept() {
+ printf("OnSSLAccept()\n");
+ HTTPSocket::OnSSLAccept();
+ }
+
+ void OnSSLConnect() {
+ printf("OnSSLConnect()\n");
+ HTTPSocket::OnSSLConnect();
+ }
+
+ void OnAccept() {
+printf("OnAccept\n");
+ }
+
+ void OnConnect() {
+printf("OnConnect\n");
+ Send("GET /index.html HTTP/1.0\r\n");
+ Send("Host: " + m_host + "\r\n");
+ Send("\r\n");
+ }
+
+ void OnFirst() {
+ }
+
+ void OnHeader(const std::string& key, const std::string& value) {
+ fprintf(stderr, "%s: %s\n", key.c_str(), value.c_str());
+ }
+
+ void OnHeaderComplete() {
+ fprintf(stderr, "\n");
+ }
+
+ void OnData(const char *buf, size_t sz) {
+ if (1||!m_first)
+ {
+ std::string str = buf;
+ str.resize( sz );
+ printf("%s", str.c_str());
+ m_first = true;
+ }
+ m_sz += sz;
+ }
+
+ void OnDelete() {
+ fprintf(stderr, "Content length: %d\n", m_sz);
+ }
+
+private:
+ std::string m_host;
+ bool m_first;
+ size_t m_sz;
+};
+
+
+int main(int argc, char *argv[])
+{
+ try
+ {
+ SocketHandler h;
+ if (argc > 1 && !strcmp(argv[1], "-server"))
+ {
+ ListenSocket<tSocket> l(h);
+ l.Bind(4443);
+ h.Add(&l);
+ while (h.GetCount())
+ {
+ h.Select(1, 0);
+ }
+ }
+ else
+ {
+ std::string host = argc > 1 ? argv[1] : "www.alhem.net";
+ tSocket sock(h, host);
+ h.Add(&sock);
+ while (h.GetCount())
+ {
+ h.Select(1, 0);
+ }
+ }
+ }
+ catch (const Exception& e)
+ {
+ printf("%s\n", e.ToString().c_str());
+ }
+}
+
+
diff --git a/src/Sockets/tests/resolve.cpp b/src/Sockets/tests/resolve.cpp
new file mode 100644
index 0000000..802b910
--- /dev/null
+++ b/src/Sockets/tests/resolve.cpp
@@ -0,0 +1,156 @@
+#include <sys/types.h>
+#ifndef _WIN32
+#include <sys/socket.h>
+#include <netdb.h>
+#endif
+#include <string.h>
+#include <string>
+#include <Utility.h>
+#include <Ipv4Address.h>
+#include <Ipv6Address.h>
+#include <assert.h>
+#include <SocketHandler.h>
+#include <StdoutLog.h>
+
+
+int main(int argc, char *argv[])
+{
+ StdoutLog log;
+ SocketHandler h(&log);
+/*
+ h.EnableResolver(9999);
+
+// printf("Waiting for resolver ...");
+ while (!h.ResolverReady())
+ ;
+// printf(" resolver ready!\n");
+*/
+ std::string hostname = argc < 2 ? "www.ipv6.org" : argv[1];
+
+ {
+ printf("Using hostname : %s\n", hostname.c_str());
+ printf("------------------------------------------- normal (old) Utility::u2ip\n");
+ ipaddr_t oa;
+ if (!Utility::u2ip(hostname, oa))
+ printf("Ipv4 lookup failed\n");
+#ifdef ENABLE_IPV6
+ in6_addr oa6;
+ if (!Utility::u2ip(hostname, oa6))
+ printf("Ipv6 lookup failed\n");
+#endif
+ std::string oname;
+ Utility::l2ip(oa, oname);
+ printf("Ipv4 : %s (old)\n", oname.c_str());
+
+#ifdef ENABLE_IPV6
+ std::string oname6;
+ Utility::l2ip(oa6, oname6);
+ printf("Ipv6 : %s (old)\n", oname6.c_str());
+#endif
+
+ printf("------------------------------------------- new Utility::u2ip, Utility::reverse\n");
+ struct sockaddr_in sa;
+ if (!Utility::u2ip(hostname, sa))
+ printf("Ipv4 lookup failed\n");
+
+ ipaddr_t a;
+ memcpy(&a, &sa.sin_addr, sizeof(a));
+ std::string l2ipname;
+ Utility::l2ip(a, l2ipname);
+ printf("Ipv4 : %s\n", l2ipname.c_str());
+
+ std::string numeric;
+ Utility::reverse((struct sockaddr *)&sa, sizeof(sa), numeric, NI_NUMERICHOST);
+ printf("Ipv4 numeric : %s\n", numeric.c_str());
+
+ std::string rname;
+ if (!Utility::reverse( (struct sockaddr *)&sa, sizeof(sa), rname))
+ printf("Reverse Ipv4 failed\n");
+ else
+ printf("Ipv4 Utility::reverse : %s\n", rname.c_str());
+
+#ifdef ENABLE_IPV6
+ printf("------------------------------------------- new Utility::u2ip, Utility::reverse (Ipv6)\n");
+ struct sockaddr_in6 sa6;
+ if (!Utility::u2ip(hostname, sa6))
+ printf("Ipv6 lookup failed\n");
+
+ std::string l2ipname6;
+ Utility::l2ip(sa6.sin6_addr, l2ipname6);
+ printf("Ipv6 : %s\n", l2ipname6.c_str());
+
+ std::string numeric6;
+ Utility::reverse((struct sockaddr *)&sa6, sizeof(sa6), numeric6, NI_NUMERICHOST);
+ printf("Ipv6 numeric : %s\n", numeric6.c_str());
+
+ std::string rname6;
+ if (!Utility::reverse( (struct sockaddr *)&sa6, sizeof(sa6), rname6))
+ printf("Reverse Ipv6 failed\n");
+ else
+ printf("Ipv6 Utility::reverse : %s\n", rname6.c_str());
+#endif
+
+ printf("-------------------------------------------\n");
+ in_addr ia;
+ /** Resolve hostname. */
+//static bool Resolve(const std::string& hostname,struct in_addr& a);
+ /** Reverse resolve (IP to hostname). */
+//static bool Reverse(struct in_addr& a,std::string& name);
+ /** Convert address struct to text. */
+//static std::string Convert(struct in_addr& a);
+ std::string name;
+ if (!Ipv4Address::Resolve(hostname, ia))
+ printf("Ipv4 lookup failed (Ipv4Address)\n");
+ memcpy(&a, &ia, sizeof(a));
+ Utility::l2ip(a, name);
+ printf("Ipv4 : %s (Ipv4Address)\n", name.c_str());
+ assert(name == l2ipname);
+ if (!Ipv4Address::Reverse(ia, name))
+ printf("Reverse Ipv4 lookup failed (Ipv4Address)\n");
+ else
+ printf("Reverse Ipv4 : %s\n", name.c_str());
+ assert(name == rname);
+ assert(Ipv4Address::Convert(ia) == l2ipname);
+
+#ifdef ENABLE_IPV6
+ printf("-------------------------------------------\n");
+ /** Resolve hostname. */
+//static bool Resolve(const std::string& hostname,struct in6_addr& a);
+ /** Reverse resolve (IP to hostname). */
+//static bool Reverse(struct in6_addr& a,std::string& name);
+ /** Convert address struct to text. */
+//static std::string Convert(struct in6_addr& a,bool mixed = false);
+ if (!Ipv6Address::Resolve(hostname, oa6))
+ printf("Ipv6 lookup failed (Ipv4Address)\n");
+ Utility::l2ip(oa6, name);
+ assert(name == l2ipname6);
+ printf("Ipv6 : %s (Ipv6Address)\n", name.c_str());
+ if (!Ipv6Address::Reverse(oa6, name))
+ printf("Reverse Ipv6 lookup failed (Ipv4Address)\n");
+ else
+ printf("Reverse Ipv6 : %s\n", name.c_str());
+ assert(name == rname6);
+ std::string mixed_false = Ipv6Address::Convert(oa6, false);
+ std::string mixed_true = Ipv6Address::Convert(oa6, true);
+ printf("Ipv6Address::Convert(false) : %s\n", mixed_false.c_str());
+ printf("Ipv6Address::Convert(true ) : %s\n", mixed_true.c_str());
+ assert(mixed_false == l2ipname6);
+#endif
+/*
+ printf("-------------------------------------------\n");
+ int protocol;
+ Utility::u2service("tcp", protocol);
+ printf("tcp: %d\n", protocol);
+ Utility::u2service("udp", protocol);
+ printf("udp: %d\n", protocol);
+ Utility::u2service("echo", protocol);
+ printf("echo: %d\n", protocol);
+*/
+ }
+ printf("\n");
+ printf("OK\n");
+
+// sleep(100);
+}
+
+
diff --git a/src/Sockets/tests/resume.cpp b/src/Sockets/tests/resume.cpp
new file mode 100644
index 0000000..e518109
--- /dev/null
+++ b/src/Sockets/tests/resume.cpp
@@ -0,0 +1,111 @@
+#include <EventHandler.h>
+#include <TcpSocket.h>
+#include <Utility.h>
+#include <IEventOwner.h>
+#include <ListenSocket.h>
+
+
+class eHandler : public EventHandler
+{
+public:
+ eHandler() : EventHandler() {}
+};
+
+
+class eSocket : public TcpSocket, public IEventOwner
+{
+public:
+ eSocket(ISocketHandler& h) : TcpSocket(h), IEventOwner(static_cast<eHandler&>(h)), m_listen_socket(NULL), m_server(false) {
+ SetLineProtocol();
+ }
+
+ bool OnConnectRetry() {
+ printf("Retrying connect\n");
+ if (GetConnectionRetries() == 5)
+ {
+ printf("Creating ListenSocket\n");
+ m_listen_socket = new ListenSocket<eSocket>(Handler());
+ if (m_listen_socket -> Bind(12345))
+ {
+ printf("Bind port 12345 failed\n");
+ }
+ m_listen_socket -> SetDeleteByHandler();
+ Handler().Add( m_listen_socket );
+ }
+ return true;
+ }
+
+ void OnAccept() {
+ m_id_stop_socket = AddEvent(5, 0);
+printf("Stop socket id: %d\n", m_id_stop_socket);
+ m_server = true;
+ }
+
+ void OnConnect() {
+ m_id_stop_listen = AddEvent(10, 0);
+printf("Stop listen id: %d\n", m_id_stop_listen);
+ }
+
+ void OnEvent(int id) {
+printf("Event id: %d\n", id);
+ if (id == m_id_stop_socket && m_server)
+ SetCloseAndDelete();
+ if (id == m_id_stop_listen && !m_server)
+ m_listen_socket -> SetCloseAndDelete();
+ }
+
+ void OnLine(const std::string& line) {
+ printf("Incoming data: %s\n", line.c_str());
+ }
+
+ void OnDelete() {
+ printf("eSocket::OnDelete(), server: %s\n", m_server ? "true" : "false");
+ }
+
+ void OnDisconnect() {
+ printf("Disconnect, server: %s\n", m_server ? "true" : "false");
+ }
+
+private:
+ ListenSocket<eSocket> *m_listen_socket;
+ int m_id_stop_socket;
+ int m_id_stop_listen;
+ bool m_server;
+};
+
+
+class Sender : public IEventOwner
+{
+public:
+ Sender(IEventHandler& h, TcpSocket& ref) : IEventOwner(h), m_socket(ref), m_count(1) {
+ AddEvent(1, 0);
+ }
+
+ void OnEvent(int id) {
+ if (static_cast<eHandler&>(EventHandler()).Valid(&m_socket))
+ m_socket.Send("Event#" + Utility::l2string(m_count++) + "\n");
+ EventHandler().AddEvent(this, 1, 0);
+ }
+
+private:
+ TcpSocket& m_socket;
+ int m_count;
+};
+
+
+int main(int argc, char *argv[])
+{
+ eHandler h;
+ eSocket sock(h);
+ sock.SetConnectTimeout(3);
+ sock.SetConnectionRetry(-1);
+#ifdef ENABLE_RECONNECT
+ sock.SetReconnect();
+#endif
+ sock.Open("localhost", 12345);
+ h.Add( &sock );
+ Sender send(h, sock);
+ h.AddEvent( &send, 1, 0 );
+ h.EventLoop();
+}
+
diff --git a/src/Sockets/tests/retry.cpp b/src/Sockets/tests/retry.cpp
new file mode 100644
index 0000000..36954a6
--- /dev/null
+++ b/src/Sockets/tests/retry.cpp
@@ -0,0 +1,67 @@
+#include <TcpSocket.h>
+#include <SocketHandler.h>
+#include <ListenSocket.h>
+
+
+ bool quit = false;
+
+/*
+ virtual bool OnConnectRetry();
+- void SetRetryClientConnect(bool x = true);
+- bool RetryClientConnect();
+ void SetConnectionRetry(int n);
+ int GetConnectionRetry();
+ void IncreaseConnectionRetries();
+ int GetConnectionRetries();
+ void ResetConnectionRetries();
+*/
+class RetrySocket : public TcpSocket
+{
+public:
+ RetrySocket(ISocketHandler& h) : TcpSocket(h) {
+ SetConnectTimeout(2);
+ SetConnectionRetry(-1);
+ }
+
+ bool OnConnectRetry() {
+ printf("Connection attempt#%d\n", GetConnectionRetries());
+ if (GetConnectionRetries() == 3)
+ {
+ ListenSocket<RetrySocket> *l = new ListenSocket<RetrySocket>(Handler());
+ if (l -> Bind(12345))
+ {
+ printf("Bind port 12345 failed\n");
+ }
+ l -> SetDeleteByHandler();
+ Handler().Add(l);
+ }
+ return true;
+ }
+
+ void OnConnect() {
+ printf("Connected\n");
+ printf("GetRemoteAddress(): %s\n", GetRemoteAddress().c_str());
+ printf("Remote address: %s\n", GetRemoteSocketAddress() -> Convert(false).c_str());
+ printf("Remote address: %s\n", GetRemoteSocketAddress() -> Convert(true).c_str());
+ SetCloseAndDelete();
+ }
+
+ void OnDelete() {
+ quit = true;
+ }
+};
+
+
+int main(int argc, char *argv[])
+{
+ SocketHandler h;
+ RetrySocket sock(h);
+ sock.Open("localhost", 12345);
+ h.Add(&sock);
+ while (!quit)
+ {
+ h.Select(0, 200000);
+ }
+}
+
+
diff --git a/src/Sockets/tests/semtest.cpp b/src/Sockets/tests/semtest.cpp
new file mode 100644
index 0000000..442d5d6
--- /dev/null
+++ b/src/Sockets/tests/semtest.cpp
@@ -0,0 +1,96 @@
+#include <stdio.h>
+#include <stdlib.h>
+#ifndef _WIN32
+#include <unistd.h>
+#include <Semaphore.h>
+#include <Mutex.h>
+#include <Thread.h>
+#include <Utility.h>
+#include <Lock.h>
+
+
+class MyThread : public Thread
+{
+public:
+ void Run() {
+ printf("Thread\n");
+ }
+};
+
+
+class SemLock
+{
+public:
+ SemLock(Semaphore& sem) : m_sem(sem) {
+ m_sem.Wait();
+ }
+ ~SemLock() {
+ m_sem.Post();
+ }
+
+private:
+ Semaphore& m_sem;
+};
+
+
+/**
+ * Return time difference between two struct timeval's, in seconds
+ * \param t0 start time
+ * \param t end time
+ */
+double Diff(struct timeval t0,struct timeval t)
+{
+ t.tv_sec -= t0.tv_sec;
+ t.tv_usec -= t0.tv_usec;
+ if (t.tv_usec < 0)
+ {
+ t.tv_usec += 1000000;
+ t.tv_sec -= 1;
+ }
+ return t.tv_sec + (double)t.tv_usec / 1000000;
+}
+
+
+static int val = 0;
+
+void lock(Mutex& m, int i)
+{
+ Lock l(m);
+ val += i;
+}
+
+
+void lock(Semaphore& s, int i)
+{
+ SemLock l(s);
+ val += i;
+}
+#endif // WIN32
+
+
+int main()
+{
+#ifndef _WIN32
+ Mutex mutex;
+ Semaphore sema(1);
+ struct timeval start;
+ struct timeval tt;
+ double d;
+
+ Utility::GetTime(&start);
+ for (int i = 0; i < 100000; i++)
+ lock(mutex, i);
+ Utility::GetTime(&tt);
+ d = Diff(start, tt);
+ printf("%.4f sec\n", d);
+
+ Utility::GetTime(&start);
+ for (int i = 0; i < 100000; i++)
+ lock(sema, i);
+ Utility::GetTime(&tt);
+ d = Diff(start, tt);
+ printf("%.4f sec\n", d);
+#endif
+}
+
+
diff --git a/src/Sockets/tests/sloppy_http.cpp b/src/Sockets/tests/sloppy_http.cpp
new file mode 100644
index 0000000..9ea79c1
--- /dev/null
+++ b/src/Sockets/tests/sloppy_http.cpp
@@ -0,0 +1,55 @@
+#include <SocketHandler.h>
+#include <TcpSocket.h>
+
+
+class GetHttp : public TcpSocket
+{
+public:
+ GetHttp(ISocketHandler& h, const char *request) : TcpSocket(h)
+ , m_request(request) {}
+
+ void OnConnect() {
+ Send( m_request );
+ }
+
+ void OnRawData( const char *buf, size_t len ) {
+ if (len > 0) {
+ std::string tmp;
+ tmp.resize( len );
+ memcpy( &tmp[0], buf, len );
+ m_response += tmp;
+ }
+ }
+
+ const std::string& Response() {
+ return m_response;
+ }
+
+private:
+ std::string m_request;
+ std::string m_response;
+};
+
+
+std::string get_http(const char *host, int port, const char *request)
+{
+ SocketHandler h;
+ GetHttp sock(h, request);
+ sock.Open( host, port );
+ h.Add(&sock);
+ while (h.GetCount()) {
+ h.Select(1, 0);
+ }
+ return sock.Response();
+}
+
+
+int main(int argc, char *argv[])
+{
+ std::string zz = get_http("www.alhem.net", 80, "GET /index.html HTTP/1.0\r\n"
+ "Host: www.alhem.net\r\n"
+ "\r\n");
+ printf("%s\n%d\n", zz.c_str(), zz.size());
+}
+
+
diff --git a/src/Sockets/tests/sockets_test.cpp b/src/Sockets/tests/sockets_test.cpp
new file mode 100644
index 0000000..78fd2bc
--- /dev/null
+++ b/src/Sockets/tests/sockets_test.cpp
@@ -0,0 +1,347 @@
+#ifdef _WIN32
+#pragma warning(disable:4786)
+#endif
+#include <StdoutLog.h>
+#include <SocketHandler.h>
+#include <TcpSocket.h>
+#include <ListenSocket.h>
+#include <Utility.h>
+#include <Parse.h>
+#include <HttpGetSocket.h>
+#include <Socket.h>
+#include <HttpDebugSocket.h>
+
+#ifdef SOCKETS_NAMESPACE
+using namespace SOCKETS_NAMESPACE;
+#endif
+
+
+class MyHandler : public SocketHandler
+{
+public:
+ MyHandler(StdLog *p) : SocketHandler(p),m_done(false),m_quit(false) {}
+ ~MyHandler() {}
+
+ void List(TcpSocket *p) {
+ for (socket_m::iterator it = m_sockets.begin(); it != m_sockets.end(); it++)
+ {
+ Socket *p0 = (*it).second;
+#ifdef ENABLE_POOL
+ if (dynamic_cast<ISocketHandler::PoolSocket *>(p0))
+ {
+ p -> Send("PoolSocket\n");
+ }
+ else
+#endif
+ if (dynamic_cast<HttpGetSocket *>(p0))
+ {
+ p -> Send("HttpGetSocket\n");
+ }
+ else
+ if (dynamic_cast<TcpSocket *>(p0))
+ {
+ p -> Send("TcpSocket\n");
+ }
+ else
+ {
+ p -> Send("Some kind of Socket\n");
+ }
+ bool r;
+ bool w;
+ bool e;
+ Get(p -> GetSocket(), r, w, e);
+ char slask[1000];
+ sprintf(slask," Read: %s Write: %s Exception: %s\n",
+ r ? "SET" : "not set",
+ w ? "SET" : "not set",
+ e ? "SET" : "not set");
+ p -> Send( slask );
+ }
+ }
+ void SetQuit() { m_quit = true; }
+ bool Quit() { return m_quit; }
+ void CheckHtml() {
+ if (m_done)
+ {
+ if (m_ok)
+ printf("Html OK:\n%s\n", m_html.c_str());
+ else
+ printf("Html Failed\n");
+ m_done = false;
+ }
+ }
+
+ std::string m_html;
+ bool m_ok;
+ bool m_done;
+
+private:
+ bool m_quit;
+};
+
+
+class MySocket : public TcpSocket
+{
+public:
+ MySocket(ISocketHandler& h) : TcpSocket(h) {
+ }
+ void OnAccept() {
+ int port = GetParent() -> GetPort();
+ Send("I'm the server at port " +
+ Utility::l2string(port) + "\n");
+ SetCloseAndDelete();
+ }
+};
+
+
+class hSocket : public HttpGetSocket
+{
+public:
+ hSocket(ISocketHandler& h,const std::string& x,const std::string& y) : HttpGetSocket(h,x,y) {}
+
+ void OnConnect() {
+ printf("hSocket::OnConnect\n");
+ HttpGetSocket::OnConnect();
+ }
+};
+
+
+class OrderSocket : public TcpSocket
+{
+public:
+ OrderSocket(ISocketHandler& h) : TcpSocket(h) {
+ SetLineProtocol();
+ }
+ Socket *Create() {
+ Handler().LogError(this, "Create", 0, "OrderSocket", LOG_LEVEL_INFO);
+ return new OrderSocket(Handler());
+ }
+ void OnAccept() {
+ Send("Cmd (get,quit,list,stop,detach,count,resolve <name>)>");
+ }
+ void OnLine(const std::string& line) {
+ Parse pa(line);
+ std::string cmd = pa.getword();
+ std::string arg = pa.getrest();
+ if (cmd == "get")
+ {
+ HttpGetSocket *p = new hSocket(Handler(), arg, "tmpfile.html");
+ p -> SetHttpVersion("HTTP/1.1");
+ p -> AddResponseHeader("Connection", "keep-alive");
+ p -> SetDeleteByHandler();
+ Handler().Add( p );
+ Send("Reading url '" + arg + "'\n");
+ }
+ else
+ if (cmd == "quit")
+ {
+ Send("Goodbye!\n");
+ SetCloseAndDelete();
+ }
+ else
+ if (cmd == "list")
+ {
+ static_cast<MyHandler&>(Handler()).List( this );
+ }
+ else
+ if (cmd == "stop")
+ {
+ static_cast<MyHandler&>(Handler()).SetQuit();
+ }
+ else
+ if (cmd == "resolve")
+ {
+ //Resolve( arg );
+ ipaddr_t a;
+ if (Utility::u2ip(arg, a))
+ {
+ std::string tmp;
+ Utility::l2ip(a, tmp);
+ Send("Resolved: " + tmp + "\n");
+ }
+ else
+ {
+ Send("Resolve failed: " + arg + "\n");
+ }
+ }
+ else
+/*
+ if (cmd == "reverse")
+ {
+ ipaddr_t a;
+ Utility::u2ip(arg, a); // ip -> ipaddr_t
+ int id = Socket::Resolve(a, 0);
+ Send("Resolve id = " + Utility::l2string(id) + "\n");
+ }
+ else
+*/
+#ifdef ENABLE_DETACH
+ if (cmd == "detach")
+ {
+ if (!Detach())
+ {
+ Send("Detach() call failed\n");
+ }
+ else
+ {
+ Send("Ok.\n");
+ }
+ }
+ else
+#endif
+ if (cmd == "count")
+ {
+ Send("Socket count: " + Utility::l2string( (long)Handler().GetCount()) + "\n");
+ }
+ else
+ {
+ Send("Huh?\n");
+ }
+ Send("Cmd>");
+ }
+ void OnDelete() {
+ printf("OrderSocket::OnDelete()\n");
+ }
+#ifdef ENABLE_RESOLVER
+ void OnResolved(int id,ipaddr_t a,port_t port)
+ {
+ }
+ void OnResolved(int id,const std::string& name,port_t port)
+ {
+ Send("Resolve id " + Utility::l2string(id) + " = " + name + "\n");
+ }
+/*
+ void OnResolved(const char *p,size_t l) {
+ printf("OnResolved, %d bytes:\n", l);
+ for (size_t i = 0; i < l; i++)
+ {
+ unsigned char c = p[i];
+ if (isprint(c))
+ printf("%c",c);
+ else
+ printf("<%02X>",c);
+ }
+ printf("\n");
+ }
+*/
+#endif
+#ifdef ENABLE_DETACH
+ void OnDetached() {
+ Send("\nDetached.\nCmd>");
+ }
+#endif
+};
+
+
+class TestSocket : public TcpSocket
+{
+public:
+ TestSocket(ISocketHandler& h) : TcpSocket(h) {
+ SetLineProtocol();
+ }
+ void OnConnect() {
+ printf("TestSocket connected, sending QUIT\n");
+ Send( "quit\n" );
+ }
+ void OnConnectFailed() {
+ printf("TestSocket::OnConnectFailed\n");
+ SetCloseAndDelete();
+ }
+ void OnLine(const std::string& line) {
+ printf("TestSocket: %s\n", line.c_str());
+ }
+ void OnDelete() {
+ printf("TestSocket::OnDelete()\n");
+ }
+#ifdef ENABLE_RESOLVER
+ void OnResolved(int id,ipaddr_t a,port_t port) {
+ printf("TestSocket::OnResolved(): %d, %08x:%d\n", id, a, port);
+ TcpSocket::OnResolved(id,a,port);
+ }
+#endif
+};
+
+
+int main()
+{
+ StdoutLog log;
+ MyHandler h(&log);
+
+#ifdef ENABLE_RESOLVER
+ h.EnableResolver(9999);
+#endif
+// Utility::ResolveLocal();
+ printf(" *** My hostname: %s\n", Utility::GetLocalHostname().c_str());
+ printf(" *** My local IP: %s\n", Utility::GetLocalAddress().c_str());
+
+ // socks4 options
+/*
+ h.SetSocks4Host("127.0.0.1");
+ h.SetSocks4Port(1080);
+ h.SetSocks4Userid("www.alhem.net");
+ h.SetSocks4TryDirect( true );
+ printf("Socks4Host: %x\n", h.GetSocks4Host());
+*/
+
+ // first server
+ ListenSocket<MySocket> l1(h);
+ if (l1.Bind(1024))
+ {
+ printf("Bind 1024 failed\n");
+ exit(-1);
+ }
+ h.Add(&l1);
+
+ // second server
+ ListenSocket<MySocket> l2(h);
+ if (l2.Bind(1025))
+ {
+ printf("Bind 1025 failed\n");
+ exit(-1);
+ }
+ h.Add(&l2);
+
+ // line server
+ ListenSocket<OrderSocket> l3(h);
+ if (l3.Bind(1027))
+ {
+ printf("Bind 1027 failed\n");
+ exit(-1);
+ }
+ h.Add(&l3);
+
+ // http debug
+ ListenSocket<HttpDebugSocket> l4(h);
+ if (l4.Bind(8080))
+ {
+ printf("Bind 8080 failed\n");
+ exit(-1);
+ }
+ h.Add(&l4);
+
+ // wait for resolver to really start
+#ifdef ENABLE_RESOLVER
+ printf("Waiting for resolver ...");
+ while (!h.ResolverReady())
+ ;
+ printf(" resolver ready!\n");
+#endif
+
+ TestSocket ts(h);
+printf(">>> TestSocket.Open\n");
+ ts.Open("localhost", 1027);
+printf(">>> Adding TestSocket\n");
+ h.Add(&ts);
+
+printf(">>> mainloop\n");
+ h.Select(0,0);
+ while (!h.Quit())
+ {
+ h.Select(1,0);
+ h.CheckSanity();
+ }
+
+ return 0;
+}
+
+
diff --git a/src/Sockets/tests/stressclient.cpp b/src/Sockets/tests/stressclient.cpp
new file mode 100644
index 0000000..4187868
--- /dev/null
+++ b/src/Sockets/tests/stressclient.cpp
@@ -0,0 +1,516 @@
+/**
+ ** \file stressclient.cpp
+ ** \date 2006-10-02
+ ** \author grymse@alhem.net
+**/
+/*
+Copyright (C) 2006 Anders Hedstrom
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+#ifdef _WIN32
+#pragma warning(disable:4786)
+#endif
+#include <StdoutLog.h>
+#include <ListenSocket.h>
+#include <SocketHandler.h>
+#include <TcpSocket.h>
+#include <Utility.h>
+#ifndef _WIN32
+#include <signal.h>
+#include <stdint.h>
+#else
+typedef __int64 int64_t;
+#endif
+#include <HttpGetSocket.h>
+
+
+static double g_min_time = 10000;
+static double g_max_time = 0;
+static double g_tot_time = 0;
+static int g_ant = 0;
+static double g_min_time2 = 10000;
+static double g_max_time2 = 0;
+static double g_tot_time2 = 0;
+static int g_ant2 = 0;
+static bool gQuit = false;
+static size_t g_max_connections = 0;
+static std::string gHost = "localhost";
+static port_t gPort = 2222;
+static bool g_b_flood = false;
+static bool g_b_off = false;
+static bool g_b_limit = false;
+static int64_t gBytesIn = 0;
+static int64_t gBytesOut = 0;
+static bool g_b_repeat = false;
+static std::string g_data;
+static size_t g_data_size = 1024;
+static bool g_b_stop = false;
+#ifdef HAVE_OPENSSL
+static bool g_b_ssl = false;
+#endif
+static bool g_b_instant = false;
+static struct timeval g_t_start;
+
+
+/**
+ * Return time difference between two struct timeval's, in seconds
+ * \param t0 start time
+ * \param t end time
+ */
+double Diff(struct timeval t0,struct timeval t)
+{
+ t.tv_sec -= t0.tv_sec;
+ t.tv_usec -= t0.tv_usec;
+ if (t.tv_usec < 0)
+ {
+ t.tv_usec += 1000000;
+ t.tv_sec -= 1;
+ }
+ return t.tv_sec + (double)t.tv_usec / 1000000;
+}
+
+
+void gettime(struct timeval *p, struct timezone *)
+{
+#ifdef _WIN32
+ FILETIME ft; // Contains a 64-bit value representing the number of 100-nanosecond intervals since January 1, 1601 (UTC).
+ GetSystemTimeAsFileTime(&ft);
+ uint64_t tt;
+ memcpy(&tt, &ft, sizeof(tt));
+ tt /= 10;
+ p->tv_sec = tt / 1000000;
+ p->tv_usec = tt % 1000000;
+#else
+ gettimeofday(p, NULL);
+#endif
+}
+
+
+void printreport()
+{
+ struct timeval tv;
+ gettime(&tv, NULL);
+ double rt = Diff(g_t_start, tv);
+ g_t_start = tv;
+ //
+ printf("\n");
+ if (g_ant)
+ printf("connect; ant: %5d min: %.4f max: %.4f med: %.4f\n", g_ant, g_min_time, g_max_time, g_tot_time / g_ant);
+ if (g_ant2)
+ printf("reply; ant: %5d min: %.4f max: %.4f med: %.4f\n", g_ant2, g_min_time2, g_max_time2, g_tot_time2 / g_ant2);
+ double mbi = (double)gBytesIn / 1024;
+ mbi /= 1024;
+ mbi /= rt;
+ double mbo = (double)gBytesOut / 1024;
+ mbo /= 1024;
+ mbo /= rt;
+ printf("bytes in: %lld", gBytesIn);
+ printf(" (%.2f MB/sec)", mbi);
+ printf(" bytes out: %lld", gBytesOut);
+ printf(" (%.2f MB/sec)", mbo);
+ printf(" time: %.2f sec\n", rt);
+}
+
+
+void printreport_reset()
+{
+ printreport();
+ //
+ g_min_time = 10000;
+ g_max_time = 0;
+ g_tot_time = 0;
+ g_ant = 0;
+ g_min_time2 = 10000;
+ g_max_time2 = 0;
+ g_tot_time2 = 0;
+ g_ant2 = 0;
+ gBytesIn = gBytesOut = 0;
+}
+
+
+class MySocket : public TcpSocket
+{
+public:
+ MySocket(ISocketHandler& h,bool one) : TcpSocket(h), m_b_client(false), m_b_one(one), m_b_created(false), m_b_active(false) {
+ gettime(&m_create, NULL);
+ SetLineProtocol();
+#ifdef HAVE_OPENSSL
+ if (g_b_ssl)
+ EnableSSL();
+#endif
+ if (g_max_connections && !m_b_one && Handler().GetCount() >= g_max_connections)
+ {
+ fprintf(stderr, "\nConnection limit reached: %d, continuing in single connection stress mode\n", (int)g_max_connections);
+ if (g_b_off)
+ printreport_reset();
+ g_b_limit = true;
+ m_b_one = true;
+ //
+ g_b_flood = g_b_repeat;
+ }
+ if (!m_b_one && Handler().GetCount() >= FD_SETSIZE - 17)
+ {
+ fprintf(stderr, "\nFD_SETSIZE connection limit reached: %d, continuing in single connection stress mode\n", (int)Handler().GetCount());
+ if (g_b_off)
+ printreport_reset();
+ g_b_limit = true;
+ m_b_one = true;
+ //
+ g_b_flood = g_b_repeat;
+ }
+ }
+ ~MySocket() {
+ }
+
+ void OnConnect() {
+ gettime(&m_connect, NULL);
+ m_b_active = true;
+ {
+ double tconnect = Diff(m_create, m_connect);
+ //
+ g_min_time = tconnect < g_min_time ? tconnect : g_min_time;
+ g_max_time = tconnect > g_max_time ? tconnect : g_max_time;
+ g_tot_time += tconnect;
+ g_ant += 1;
+ }
+ SendBlock();
+ m_b_client = true;
+ }
+
+ void SendBlock() {
+ gettime(&m_send, NULL);
+ Send(g_data + "\n");
+ }
+
+ void OnLine(const std::string& line) {
+ gettime(&m_reply, NULL);
+ m_b_active = true;
+ {
+ double treply = Diff(m_send, m_reply);
+ //
+ g_min_time2 = treply < g_min_time2 ? treply : g_min_time2;
+ g_max_time2 = treply > g_max_time2 ? treply : g_max_time2;
+ g_tot_time2 += treply;
+ g_ant2 += 1;
+ }
+ //
+ if (line != g_data)
+ {
+ fprintf(stderr, "\n%s\n%s\n", line.c_str(), g_data.c_str());
+ fprintf(stderr, "(reply did not match data - exiting)\n");
+ exit(-1);
+ }
+ //
+ gBytesIn += GetBytesReceived(true);
+ gBytesOut += GetBytesSent(true);
+ if (m_b_one)
+ {
+ SetCloseAndDelete();
+ }
+ else
+ if (g_b_repeat && g_b_limit)
+ {
+ SendBlock();
+ }
+ // add another
+ if (!m_b_created && (!g_b_limit || !g_b_off) && !g_b_instant)
+ {
+ MySocket *p = new MySocket(Handler(), m_b_one);
+ p -> SetDeleteByHandler();
+ p -> Open(gHost, gPort);
+ Handler().Add(p);
+ m_b_created = true;
+ }
+ }
+
+ bool IsActive() {
+ bool b = m_b_active;
+ m_b_active = false;
+ return b;
+ }
+
+private:
+ bool m_b_client;
+ bool m_b_one;
+ bool m_b_created;
+ bool m_b_active;
+ struct timeval m_create;
+ struct timeval m_connect;
+ struct timeval m_send;
+ struct timeval m_reply;
+};
+
+
+class MyHttpSocket : public HttpGetSocket
+{
+public:
+ MyHttpSocket(ISocketHandler& h,const std::string& url) : HttpGetSocket(h,url), m_url(url) {
+ gettime(&m_create, NULL);
+ AddResponseHeader("content-length", Utility::l2string(g_data_size));
+ }
+ ~MyHttpSocket() {}
+
+ void OnConnect() {
+ gettime(&m_connect, NULL);
+ {
+ double tconnect = Diff(m_create, m_connect);
+ //
+ g_min_time = tconnect < g_min_time ? tconnect : g_min_time;
+ g_max_time = tconnect > g_max_time ? tconnect : g_max_time;
+ g_tot_time += tconnect;
+ g_ant += 1;
+ }
+ gettime(&m_send, NULL);
+
+ // send request header
+ HttpGetSocket::OnConnect();
+
+ // send body
+ Send(g_data);
+ }
+
+ void OnContent() {
+ gettime(&m_reply, NULL);
+ {
+ double treply = Diff(m_send, m_reply);
+ //
+ g_min_time2 = treply < g_min_time2 ? treply : g_min_time2;
+ g_max_time2 = treply > g_max_time2 ? treply : g_max_time2;
+ g_tot_time2 += treply;
+ g_ant2 += 1;
+ }
+ CreateNew();
+ }
+ void CreateNew() {
+ if (g_b_off)
+ return;
+ MyHttpSocket *p = new MyHttpSocket(Handler(), m_url);
+ p -> SetDeleteByHandler();
+ Handler().Add(p);
+ SetCloseAndDelete();
+ }
+
+private:
+ std::string m_url;
+ struct timeval m_create;
+ struct timeval m_connect;
+ struct timeval m_send;
+ struct timeval m_reply;
+};
+
+
+#ifndef _WIN32
+void sigint(int)
+{
+ printreport();
+ gQuit = true;
+}
+
+
+void sigusr1(int)
+{
+ g_b_flood = true;
+}
+
+
+void sigusr2(int)
+{
+ printreport_reset();
+}
+#endif
+
+
+class MyHandler : public SocketHandler
+{
+public:
+ MyHandler() : SocketHandler() {
+ }
+ MyHandler(StdoutLog *p) : SocketHandler(p) {
+ }
+ ~MyHandler() {
+ }
+ void Flood() {
+ for (socket_m::iterator it = m_sockets.begin(); it != m_sockets.end(); it++)
+ {
+ Socket *p0 = it -> second;
+ MySocket *p = dynamic_cast<MySocket *>(p0);
+ if (p)
+ {
+ p -> SendBlock();
+ }
+ }
+ }
+ void Report() {
+ int ant = 0;
+ int act = 0;
+ for (socket_m::iterator it = m_sockets.begin(); it != m_sockets.end(); it++)
+ {
+ MySocket *p = dynamic_cast<MySocket *>(it -> second);
+ if (p)
+ {
+ ant++;
+ if (p -> IsActive())
+ {
+ act++;
+ }
+ }
+ }
+ printf("Number of //stress// sockets: %d Active: %d\n", ant, act);
+ }
+};
+
+
+int main(int argc,char *argv[])
+{
+ bool many = false;
+ bool one = false;
+ bool enableLog = false;
+ bool http = false;
+ std::string url;
+ time_t report_period = 10;
+ for (int i = 1; i < argc; i++)
+ {
+ if (!strcmp(argv[i], "-many"))
+ many = true;
+ if (!strcmp(argv[i], "-one"))
+ one = true;
+ if (*argv[i] == '-' && strlen(argv[i]) > 1 && isdigit(argv[i][1]) )
+ g_max_connections = atoi(argv[i] + 1);
+ if (!strcmp(argv[i], "-host") && i < argc - 1)
+ gHost = argv[++i];
+ if (!strcmp(argv[i], "-port") && i < argc - 1)
+ gPort = atoi(argv[++i]);
+ if (!strcmp(argv[i], "-off"))
+ g_b_off = true;
+ if (!strcmp(argv[i], "-repeat"))
+ g_b_repeat = true;
+ if (!strcmp(argv[i], "-size") && i < argc - 1)
+ g_data_size = atoi(argv[++i]);
+ if (!strcmp(argv[i], "-log"))
+ enableLog = true;
+ if (!strcmp(argv[i], "-time") && i < argc - 1)
+ report_period = atoi(argv[++i]);
+ if (!strcmp(argv[i], "-stop"))
+ g_b_stop = true;
+#ifdef HAVE_OPENSSL
+ if (!strcmp(argv[i], "-ssl"))
+ g_b_ssl = true;
+#endif
+ if (!strcmp(argv[i], "-instant"))
+ g_b_instant = true;
+ if (!strcmp(argv[i], "-http"))
+ http = true;
+ if (!strcmp(argv[i], "-url") && i < argc - 1)
+ url = argv[++i];
+ }
+ if (argc < 2 || (!many && !one && !g_max_connections && !http) )
+ {
+ printf("Usage: %s [mode] [options]\n", *argv);
+ printf(" Modes (only use one of these):\n");
+ printf(" -many start max number of connections\n");
+ printf(" -one open - close - repeat\n");
+ printf(" -nn open nn connections, then start -one mode\n");
+ printf(" -http send/receive http request/response\n");
+ printf(" Options:\n");
+ printf(" -host xx host to connect to\n");
+ printf(" -port nn port number to connection to\n");
+ printf(" -off turn off new connections when connection limit reached\n");
+ printf(" -repeat send new block when reply is received\n");
+ printf(" -size nn size of block to send, default is 1024 bytes\n");
+ printf(" -log enable debug log\n");
+ printf(" -time nn time between reports, default 10s\n");
+ printf(" -stop stop after time elapsed\n");
+ printf(" -instant create all sockets at once\n");
+#ifdef HAVE_OPENSSL
+ printf(" -ssl use ssl\n");
+#endif
+ printf(" -url xx url to use in http mode (default http://<host>:<port>/)\n");
+ exit(-1);
+ }
+ fprintf(stderr, "Using data size: %d bytes\n", (int)g_data_size);
+ std::string chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ while (g_data.size() < g_data_size)
+ {
+ g_data += chars[rand() % chars.size()];
+ }
+#ifndef _WIN32
+ signal(SIGINT, sigint);
+ signal(SIGUSR1, sigusr1);
+ signal(SIGUSR2, sigusr2);
+ signal(SIGPIPE, SIG_IGN);
+#endif
+ StdoutLog *log = enableLog ? new StdoutLog() : NULL;
+ MyHandler h(log);
+ if (http)
+ {
+ if (!url.size())
+ {
+ url = "http://" + gHost + ":" + Utility::l2string(gPort) + "/";
+ }
+ MyHttpSocket *s = new MyHttpSocket(h, url);
+ s -> SetDeleteByHandler();
+ h.Add(s);
+ }
+ else
+ if (g_b_instant)
+ {
+ for (size_t i = 0; i < g_max_connections; i++)
+ {
+ MySocket *s = new MySocket(h, one);
+ s -> SetDeleteByHandler();
+ s -> Open(gHost, gPort);
+ h.Add(s);
+ }
+ g_b_limit = true;
+ }
+ else
+ {
+ MySocket *s = new MySocket(h, one);
+ s -> SetDeleteByHandler();
+ s -> Open(gHost, gPort);
+ h.Add(s);
+ }
+ time_t t = time(NULL);
+ gettime(&g_t_start, NULL);
+ while (!gQuit)
+ {
+ h.Select(1, 0);
+ if (g_b_flood)
+ {
+ fprintf(stderr, "\nFlooding\n");
+ h.Flood();
+ g_b_flood = false;
+ }
+ if (time(NULL) - t >= report_period) // report
+ {
+ t = time(NULL);
+ printreport_reset();
+ h.Report();
+ if (g_b_stop)
+ {
+ gQuit = true;
+ }
+ }
+ }
+ fprintf(stderr, "\nExiting...\n");
+ if (log)
+ {
+// delete log;
+ }
+ return 0;
+}
+
+
diff --git a/src/Sockets/tests/x.cpp b/src/Sockets/tests/x.cpp
new file mode 100644
index 0000000..2ca9b26
--- /dev/null
+++ b/src/Sockets/tests/x.cpp
@@ -0,0 +1,298 @@
+#include <SocketHandler.h>
+#include <TcpSocket.h>
+#include <StdoutLog.h>
+#ifndef _WIN32
+#include <signal.h>
+#endif
+#include <IEventOwner.h>
+#include <EventHandler.h>
+
+#define HOST "localhost"
+#define PORT 2222
+
+#define TIME_US 250000
+
+#define DEB(x) x
+
+
+static bool quit = false;
+static EventHandler *ph = NULL;
+
+static int lc = 0;
+static int l2c = 0;
+static int l3c = 0;
+
+
+#ifndef _WIN32
+void sighandler(int s)
+{
+ quit = true;
+ ph -> SetQuit();
+}
+
+
+void sigpipe(int s)
+{
+}
+#endif
+
+
+class evHandler : public EventHandler
+{
+public:
+ evHandler() : EventHandler() {}
+ evHandler(StdLog *p) : EventHandler(p) {}
+
+ void CloseAll() {
+ for (socket_m::iterator it = m_sockets.begin(); it != m_sockets.end(); it++)
+ {
+ Socket *p = it -> second;
+ p -> SetCloseAndDelete();
+ }
+ }
+
+};
+
+
+class lSocket : public TcpSocket, public IEventOwner
+{
+public:
+ lSocket(ISocketHandler& h, bool first = false) : TcpSocket(h), IEventOwner(static_cast<evHandler&>(h)), m_id(0), m_first(first) {
+ SetLineProtocol();
+ lc++;
+ }
+ ~lSocket() {
+ }
+
+ void OnConnect() {
+ if (!m_id)
+ {
+ m_id = AddEvent(0, TIME_US);
+ }
+ printf(".");
+ fflush(stdout);
+ }
+ void OnConnectFailed() {
+ printf("lSocket::OnConnectFailed\n");
+ }
+
+ void OnDelete() {
+ if (m_first)
+ printf("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"
+ "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"
+ "@@@@@@@@@@@@@@ OnDelete() first @@@@@@@@@@@@@@@@@@\n"
+ "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"
+ "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");
+ }
+
+ void OnEvent(int id) {
+ if (id != m_id)
+ {
+ printf("ID MISMATCH!\n");
+ exit(-1);
+ }
+ if (!quit)
+ {
+ lSocket *p = new lSocket(Handler());
+ p -> SetDeleteByHandler();
+ p -> Open(HOST, PORT);
+ Handler().Add(p);
+ }
+ static_cast<evHandler&>(Handler()).SetQuit( quit );
+ SetCloseAndDelete();
+ }
+
+private:
+ int m_id;
+ bool m_first;
+};
+
+
+class l2Socket : public TcpSocket, public IEventOwner
+{
+public:
+ l2Socket(ISocketHandler& h, bool first = false) : TcpSocket(h), IEventOwner(static_cast<evHandler&>(h)), m_id(0), m_first(first) {
+ SetLineProtocol();
+ l2c++;
+ }
+ ~l2Socket() {
+ }
+
+ void OnConnect() {
+ printf(".");
+ fflush(stdout);
+ }
+ void OnConnectFailed() {
+ printf("l2Socket::OnConnectFailed\n");
+ }
+
+ void OnLine(const std::string& line) {
+ if (!m_id)
+ {
+ m_id = AddEvent(0, TIME_US);
+ }
+ }
+
+ void OnDelete() {
+ if (m_first)
+ printf("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"
+ "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"
+ "@@@@@@@@@@@@@@ OnDelete() first @@@@@@@@@@@@@@@@@@\n"
+ "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"
+ "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");
+ }
+
+ void OnEvent(int id) {
+ if (id != m_id)
+ {
+ printf("ID MISMATCH!\n");
+ exit(-1);
+ }
+ if (!quit)
+ {
+ l2Socket *p = new l2Socket(Handler());
+ p -> SetDeleteByHandler();
+ p -> Open(HOST, PORT);
+ Handler().Add(p);
+ }
+ static_cast<evHandler&>(Handler()).SetQuit( quit );
+ SetCloseAndDelete();
+ }
+
+private:
+ int m_id;
+ bool m_first;
+};
+
+
+class l3Socket : public TcpSocket, public IEventOwner
+{
+public:
+ l3Socket(ISocketHandler& h, bool first = false) : TcpSocket(h), IEventOwner(static_cast<evHandler&>(h)), m_ehlo(false), m_id(0), m_first(first) {
+ SetLineProtocol();
+ l3c++;
+ }
+ ~l3Socket() {
+ }
+
+ void OnConnect() {
+ printf(".");
+ fflush(stdout);
+ }
+ void OnConnectFailed() {
+ printf("l3Socket::OnConnectFailed\n");
+ }
+
+ void OnLine(const std::string& line) {
+ if (!m_ehlo)
+ {
+ Send("EHLO alhem.net\r\n");
+ m_ehlo = true;
+ }
+ else
+ if (!m_id)
+ {
+ m_id = AddEvent(0, TIME_US);
+ }
+ }
+
+ void OnDelete() {
+ if (m_first)
+ printf("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"
+ "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"
+ "@@@@@@@@@@@@@@ OnDelete() first @@@@@@@@@@@@@@@@@@\n"
+ "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"
+ "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");
+ }
+
+ void OnEvent(int id) {
+ if (id != m_id)
+ {
+ printf("ID MISMATCH!\n");
+ exit(-1);
+ }
+ if (!quit)
+ {
+ l3Socket *p = new l3Socket(Handler());
+ p -> SetDeleteByHandler();
+ p -> Open(HOST, PORT);
+ Handler().Add(p);
+ }
+ static_cast<evHandler&>(Handler()).SetQuit( quit );
+ Send("QUIT\r\n");
+ }
+
+private:
+ bool m_ehlo;
+ int m_id;
+ bool m_first;
+};
+
+
+int main(int argc, char *argv[])
+{
+#ifndef _WIN32
+ signal(SIGHUP, sighandler);
+ signal(SIGINT, sighandler);
+ signal(SIGPIPE, sigpipe);
+#endif
+
+ time_t tstart = time(NULL);
+ {
+ StdoutLog log;
+ {
+ evHandler h(&log);
+ ph = &h;
+ {
+ lSocket sock(h, true);
+ sock.Open(HOST, PORT);
+ h.Add(&sock);
+ {
+ l2Socket sock2(h, true);
+ sock2.Open(HOST, PORT);
+ h.Add(&sock2);
+ {
+ l3Socket sock3(h, true);
+ sock3.Open(HOST, PORT);
+ h.Add(&sock3);
+
+ h.EventLoop();
+ h.CloseAll();
+
+ // %! one socket refuses to go away
+ while (h.GetCount() > 1)
+ {
+ h.Select(1, 0);
+ }
+ printf("Exiting 1...\n");
+ fflush(stdout);
+ }
+ printf("Exiting 2...\n");
+ fflush(stdout);
+ }
+ printf("Exiting 3...\n");
+ fflush(stdout);
+ }
+ printf("Exiting 4...\n");
+ fflush(stdout);
+ }
+ printf("Exiting 5...\n");
+ fflush(stdout);
+ }
+ printf("Exiting 6...\n");
+ fflush(stdout);
+
+ time_t tstop = time(NULL);
+
+ time_t total = tstop - tstart + 1;
+
+ printf("lc: %d\n", lc);
+ printf("l2c: %d\n", l2c);
+ printf("l3c: %d\n", l3c);
+
+ printf("lc: %f\n", (double)lc / (double)total);
+ printf("l2c: %f\n", (double)l2c / (double)total);
+ printf("l3c: %f\n", (double)l3c / (double)total);
+}
+
+