From fa4f4a8a50c4bab3a3e247fb7186a7f9a00dfc11 Mon Sep 17 00:00:00 2001 From: Othmar Gsenger Date: Mon, 3 Dec 2007 10:51:16 +0000 Subject: Added syncsocket --- Sockets/tests/Makefile | 73 ++++++ Sockets/tests/base64.cpp | 34 +++ Sockets/tests/copy.cpp | 264 +++++++++++++++++++++ Sockets/tests/crlf.cpp | 139 +++++++++++ Sockets/tests/echoserver.cpp | 237 +++++++++++++++++++ Sockets/tests/events.cpp | 212 +++++++++++++++++ Sockets/tests/http.cpp | 65 ++++++ Sockets/tests/http_post.cpp | 107 +++++++++ Sockets/tests/httpd.cpp | 109 +++++++++ Sockets/tests/https.cpp | 113 +++++++++ Sockets/tests/resolve.cpp | 156 +++++++++++++ Sockets/tests/resume.cpp | 111 +++++++++ Sockets/tests/retry.cpp | 67 ++++++ Sockets/tests/semtest.cpp | 96 ++++++++ Sockets/tests/sloppy_http.cpp | 55 +++++ Sockets/tests/sockets_test.cpp | 347 +++++++++++++++++++++++++++ Sockets/tests/stressclient.cpp | 516 +++++++++++++++++++++++++++++++++++++++++ Sockets/tests/x.cpp | 298 ++++++++++++++++++++++++ 18 files changed, 2999 insertions(+) create mode 100644 Sockets/tests/Makefile create mode 100644 Sockets/tests/base64.cpp create mode 100644 Sockets/tests/copy.cpp create mode 100644 Sockets/tests/crlf.cpp create mode 100644 Sockets/tests/echoserver.cpp create mode 100644 Sockets/tests/events.cpp create mode 100644 Sockets/tests/http.cpp create mode 100644 Sockets/tests/http_post.cpp create mode 100644 Sockets/tests/httpd.cpp create mode 100644 Sockets/tests/https.cpp create mode 100644 Sockets/tests/resolve.cpp create mode 100644 Sockets/tests/resume.cpp create mode 100644 Sockets/tests/retry.cpp create mode 100644 Sockets/tests/semtest.cpp create mode 100644 Sockets/tests/sloppy_http.cpp create mode 100644 Sockets/tests/sockets_test.cpp create mode 100644 Sockets/tests/stressclient.cpp create mode 100644 Sockets/tests/x.cpp (limited to 'Sockets/tests') diff --git a/Sockets/tests/Makefile b/Sockets/tests/Makefile new file mode 100644 index 0000000..0bbabf8 --- /dev/null +++ b/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/Sockets/tests/base64.cpp b/Sockets/tests/base64.cpp new file mode 100644 index 0000000..722439d --- /dev/null +++ b/Sockets/tests/base64.cpp @@ -0,0 +1,34 @@ +#include + +#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/Sockets/tests/copy.cpp b/Sockets/tests/copy.cpp new file mode 100644 index 0000000..2134ac2 --- /dev/null +++ b/Sockets/tests/copy.cpp @@ -0,0 +1,264 @@ +#include +#include +#include +#include + +#define BUFSZ 7024 + +#ifdef _WIN32 +#define MIN(a,b) (a 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 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 ] [-port ] []\n", *argv); + fprintf(stderr, " Will run as host only if 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 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::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/Sockets/tests/crlf.cpp b/Sockets/tests/crlf.cpp new file mode 100644 index 0000000..34500c4 --- /dev/null +++ b/Sockets/tests/crlf.cpp @@ -0,0 +1,139 @@ +#include +#include +#include + + +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 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/Sockets/tests/echoserver.cpp b/Sockets/tests/echoserver.cpp new file mode 100644 index 0000000..45cb6c2 --- /dev/null +++ b/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 +#include +#include +#include +#ifndef _WIN32 +#include +#endif +#include + + +#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 l(h); + ListenSocket 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/Sockets/tests/events.cpp b/Sockets/tests/events.cpp new file mode 100644 index 0000000..5d08973 --- /dev/null +++ b/Sockets/tests/events.cpp @@ -0,0 +1,212 @@ +#include +#include +#include +#include +#include +#include + + +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(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(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 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/Sockets/tests/http.cpp b/Sockets/tests/http.cpp new file mode 100644 index 0000000..6800699 --- /dev/null +++ b/Sockets/tests/http.cpp @@ -0,0 +1,65 @@ +#include +#include + + +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/Sockets/tests/http_post.cpp b/Sockets/tests/http_post.cpp new file mode 100644 index 0000000..3b0b830 --- /dev/null +++ b/Sockets/tests/http_post.cpp @@ -0,0 +1,107 @@ +#include +#include +#include +#include +#include +#include +#include + + +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(""); + 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 l(h); + if (l.Bind(1028)) + { + printf("Bind port 1028 failed\n"); + return -1; + } + h.Add(&l); + ListenSocket 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/Sockets/tests/httpd.cpp b/Sockets/tests/httpd.cpp new file mode 100644 index 0000000..e1106a0 --- /dev/null +++ b/Sockets/tests/httpd.cpp @@ -0,0 +1,109 @@ +#include +#include +#include +#include + + +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 l(h); + if (l.Bind(1028)) + { + printf("Bind port 1028 failed\n"); + return -1; + } + h.Add(&l); + ListenSocket 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/Sockets/tests/https.cpp b/Sockets/tests/https.cpp new file mode 100644 index 0000000..45b36ff --- /dev/null +++ b/Sockets/tests/https.cpp @@ -0,0 +1,113 @@ +#include +#include +#include +#include + + +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 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/Sockets/tests/resolve.cpp b/Sockets/tests/resolve.cpp new file mode 100644 index 0000000..802b910 --- /dev/null +++ b/Sockets/tests/resolve.cpp @@ -0,0 +1,156 @@ +#include +#ifndef _WIN32 +#include +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include + + +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/Sockets/tests/resume.cpp b/Sockets/tests/resume.cpp new file mode 100644 index 0000000..e518109 --- /dev/null +++ b/Sockets/tests/resume.cpp @@ -0,0 +1,111 @@ +#include +#include +#include +#include +#include + + +class eHandler : public EventHandler +{ +public: + eHandler() : EventHandler() {} +}; + + +class eSocket : public TcpSocket, public IEventOwner +{ +public: + eSocket(ISocketHandler& h) : TcpSocket(h), IEventOwner(static_cast(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(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 *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(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/Sockets/tests/retry.cpp b/Sockets/tests/retry.cpp new file mode 100644 index 0000000..36954a6 --- /dev/null +++ b/Sockets/tests/retry.cpp @@ -0,0 +1,67 @@ +#include +#include +#include + + + 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 *l = new ListenSocket(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/Sockets/tests/semtest.cpp b/Sockets/tests/semtest.cpp new file mode 100644 index 0000000..442d5d6 --- /dev/null +++ b/Sockets/tests/semtest.cpp @@ -0,0 +1,96 @@ +#include +#include +#ifndef _WIN32 +#include +#include +#include +#include +#include +#include + + +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/Sockets/tests/sloppy_http.cpp b/Sockets/tests/sloppy_http.cpp new file mode 100644 index 0000000..9ea79c1 --- /dev/null +++ b/Sockets/tests/sloppy_http.cpp @@ -0,0 +1,55 @@ +#include +#include + + +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/Sockets/tests/sockets_test.cpp b/Sockets/tests/sockets_test.cpp new file mode 100644 index 0000000..78fd2bc --- /dev/null +++ b/Sockets/tests/sockets_test.cpp @@ -0,0 +1,347 @@ +#ifdef _WIN32 +#pragma warning(disable:4786) +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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(p0)) + { + p -> Send("PoolSocket\n"); + } + else +#endif + if (dynamic_cast(p0)) + { + p -> Send("HttpGetSocket\n"); + } + else + if (dynamic_cast(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 )>"); + } + 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(Handler()).List( this ); + } + else + if (cmd == "stop") + { + static_cast(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 l1(h); + if (l1.Bind(1024)) + { + printf("Bind 1024 failed\n"); + exit(-1); + } + h.Add(&l1); + + // second server + ListenSocket l2(h); + if (l2.Bind(1025)) + { + printf("Bind 1025 failed\n"); + exit(-1); + } + h.Add(&l2); + + // line server + ListenSocket l3(h); + if (l3.Bind(1027)) + { + printf("Bind 1027 failed\n"); + exit(-1); + } + h.Add(&l3); + + // http debug + ListenSocket 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/Sockets/tests/stressclient.cpp b/Sockets/tests/stressclient.cpp new file mode 100644 index 0000000..4187868 --- /dev/null +++ b/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 +#include +#include +#include +#include +#ifndef _WIN32 +#include +#include +#else +typedef __int64 int64_t; +#endif +#include + + +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(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(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://:/)\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/Sockets/tests/x.cpp b/Sockets/tests/x.cpp new file mode 100644 index 0000000..2ca9b26 --- /dev/null +++ b/Sockets/tests/x.cpp @@ -0,0 +1,298 @@ +#include +#include +#include +#ifndef _WIN32 +#include +#endif +#include +#include + +#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(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(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(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(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(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(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); +} + + -- cgit v1.2.3