summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOthmar Gsenger <otti@anytun.org>2007-12-03 10:51:16 +0000
committerOthmar Gsenger <otti@anytun.org>2007-12-03 10:51:16 +0000
commitfa4f4a8a50c4bab3a3e247fb7186a7f9a00dfc11 (patch)
tree5ff84c3c71e6d3dadbaf9e13d3fdd84ab2691ca6
parentadded ssl tools (diff)
Added syncsocket
-rw-r--r--Makefile24
-rw-r--r--README8
-rw-r--r--Sockets/Ajp13Socket.cpp404
-rw-r--r--Sockets/Ajp13Socket.h69
-rw-r--r--Sockets/AjpBaseSocket.cpp258
-rw-r--r--Sockets/AjpBaseSocket.h83
-rw-r--r--Sockets/Base64.cpp272
-rw-r--r--Sockets/Base64.h77
-rw-r--r--Sockets/Debug.cpp79
-rw-r--r--Sockets/Debug.h75
-rw-r--r--Sockets/DevCpp/Sockets.dev1129
-rw-r--r--Sockets/DevCpp/Test.dev59
-rw-r--r--Sockets/Event.cpp85
-rw-r--r--Sockets/Event.h76
-rw-r--r--Sockets/EventHandler.cpp223
-rw-r--r--Sockets/EventHandler.h85
-rw-r--r--Sockets/EventTime.cpp105
-rw-r--r--Sockets/EventTime.h77
-rw-r--r--Sockets/Exception.cpp48
-rw-r--r--Sockets/Exception.h58
-rw-r--r--Sockets/File.cpp169
-rw-r--r--Sockets/File.h84
-rw-r--r--Sockets/HTTPSocket.cpp413
-rw-r--r--Sockets/HTTPSocket.h152
-rw-r--r--Sockets/HttpBaseSocket.cpp204
-rw-r--r--Sockets/HttpBaseSocket.h76
-rw-r--r--Sockets/HttpClientSocket.cpp277
-rw-r--r--Sockets/HttpClientSocket.h121
-rw-r--r--Sockets/HttpDebugSocket.cpp125
-rw-r--r--Sockets/HttpDebugSocket.h70
-rw-r--r--Sockets/HttpGetSocket.cpp114
-rw-r--r--Sockets/HttpGetSocket.h66
-rw-r--r--Sockets/HttpPostSocket.cpp294
-rw-r--r--Sockets/HttpPostSocket.h94
-rw-r--r--Sockets/HttpPutSocket.cpp125
-rw-r--r--Sockets/HttpPutSocket.h83
-rw-r--r--Sockets/HttpRequest.cpp358
-rw-r--r--Sockets/HttpRequest.h125
-rw-r--r--Sockets/HttpResponse.cpp201
-rw-r--r--Sockets/HttpResponse.h82
-rw-r--r--Sockets/HttpTransaction.cpp244
-rw-r--r--Sockets/HttpTransaction.h94
-rw-r--r--Sockets/HttpdCookies.cpp270
-rw-r--r--Sockets/HttpdCookies.h89
-rw-r--r--Sockets/HttpdForm.cpp616
-rw-r--r--Sockets/HttpdForm.h118
-rw-r--r--Sockets/HttpdSocket.cpp528
-rw-r--r--Sockets/HttpdSocket.h106
-rw-r--r--Sockets/IBase.h44
-rw-r--r--Sockets/IEventHandler.h75
-rw-r--r--Sockets/IEventOwner.cpp79
-rw-r--r--Sockets/IEventOwner.h77
-rw-r--r--Sockets/IFile.h71
-rw-r--r--Sockets/IHttpServer.h56
-rw-r--r--Sockets/ISocketHandler.h233
-rw-r--r--Sockets/Ipv4Address.cpp214
-rw-r--r--Sockets/Ipv4Address.h98
-rw-r--r--Sockets/Ipv6Address.cpp270
-rw-r--r--Sockets/Ipv6Address.h107
-rw-r--r--Sockets/ListenSocket.h420
-rw-r--r--Sockets/Lock.cpp55
-rw-r--r--Sockets/Lock.h59
-rw-r--r--Sockets/Makefile154
-rw-r--r--Sockets/Makefile.Defines.linux-x86-3228
-rw-r--r--Sockets/Makefile.Defines.macosx28
-rw-r--r--Sockets/Makefile.Defines.solaris829
-rw-r--r--Sockets/Makefile.Defines.solaris9-sparc-6429
-rw-r--r--Sockets/Makefile.Defines.win32-cygwin26
-rw-r--r--Sockets/Makefile.solaris9-sparc-6470
-rw-r--r--Sockets/Makefile.version49
-rw-r--r--Sockets/MemFile.cpp288
-rw-r--r--Sockets/MemFile.h100
-rw-r--r--Sockets/Mutex.cpp81
-rw-r--r--Sockets/Mutex.h68
-rwxr-xr-xSockets/OSX.zipbin0 -> 16669 bytes
-rw-r--r--Sockets/Parse.cpp321
-rw-r--r--Sockets/Parse.h101
-rw-r--r--Sockets/Project.net/Sockets/Sockets.sln30
-rw-r--r--Sockets/Project.net/Sockets/Sockets.vcproj452
-rw-r--r--Sockets/Project.net/Test/Test.vcproj140
-rw-r--r--Sockets/Project/Sockets.dsp526
-rw-r--r--Sockets/Project/Sockets.dsw68
-rw-r--r--Sockets/Project/Test.dsp102
-rw-r--r--Sockets/Project/echoserver.dsp100
-rw-r--r--Sockets/Project/stressclient.dsp100
-rw-r--r--Sockets/README.macosx3
-rw-r--r--Sockets/RandomNumber.cpp116
-rw-r--r--Sockets/RandomNumber.h202
-rw-r--r--Sockets/ResolvServer.cpp97
-rw-r--r--Sockets/ResolvServer.h73
-rw-r--r--Sockets/ResolvSocket.cpp436
-rw-r--r--Sockets/ResolvSocket.h106
-rw-r--r--Sockets/SSLInitializer.cpp144
-rw-r--r--Sockets/SSLInitializer.h76
-rw-r--r--Sockets/SctpSocket.cpp496
-rw-r--r--Sockets/SctpSocket.h110
-rw-r--r--Sockets/Semaphore.cpp76
-rw-r--r--Sockets/Semaphore.h67
-rw-r--r--Sockets/SmtpdSocket.cpp234
-rw-r--r--Sockets/SmtpdSocket.h143
-rw-r--r--Sockets/Socket.cpp1896
-rw-r--r--Sockets/Socket.h738
-rw-r--r--Sockets/SocketAddress.h95
-rw-r--r--Sockets/SocketHandler.cpp1422
-rw-r--r--Sockets/SocketHandler.h266
-rw-r--r--Sockets/Sockets-config.cpp121
-rw-r--r--Sockets/StdLog.h74
-rw-r--r--Sockets/StdoutLog.cpp96
-rw-r--r--Sockets/StdoutLog.h57
-rw-r--r--Sockets/StreamSocket.cpp169
-rw-r--r--Sockets/StreamSocket.h127
-rw-r--r--Sockets/TcpSocket.cpp1729
-rw-r--r--Sockets/TcpSocket.h355
-rw-r--r--Sockets/Thread.cpp166
-rw-r--r--Sockets/Thread.h100
-rw-r--r--Sockets/UdpSocket.cpp843
-rw-r--r--Sockets/UdpSocket.h215
-rw-r--r--Sockets/Utility.cpp953
-rw-r--r--Sockets/Utility.h153
-rw-r--r--Sockets/ajp13.h91
-rw-r--r--Sockets/gpl.txt340
-rwxr-xr-xSockets/mkdot.sh13
-rw-r--r--Sockets/socket_include.cpp90
-rw-r--r--Sockets/socket_include.h288
-rw-r--r--Sockets/sockets-config.h97
-rw-r--r--Sockets/tests/Makefile73
-rw-r--r--Sockets/tests/base64.cpp34
-rw-r--r--Sockets/tests/copy.cpp264
-rw-r--r--Sockets/tests/crlf.cpp139
-rw-r--r--Sockets/tests/echoserver.cpp237
-rw-r--r--Sockets/tests/events.cpp212
-rw-r--r--Sockets/tests/http.cpp65
-rw-r--r--Sockets/tests/http_post.cpp107
-rw-r--r--Sockets/tests/httpd.cpp109
-rw-r--r--Sockets/tests/https.cpp113
-rw-r--r--Sockets/tests/resolve.cpp156
-rw-r--r--Sockets/tests/resume.cpp111
-rw-r--r--Sockets/tests/retry.cpp67
-rw-r--r--Sockets/tests/semtest.cpp96
-rw-r--r--Sockets/tests/sloppy_http.cpp55
-rw-r--r--Sockets/tests/sockets_test.cpp347
-rw-r--r--Sockets/tests/stressclient.cpp516
-rw-r--r--Sockets/tests/x.cpp298
-rw-r--r--doc/html/PracticalSocket_8cpp.html2
-rw-r--r--doc/html/PracticalSocket_8h-source.html2
-rw-r--r--doc/html/PracticalSocket_8h.html2
-rw-r--r--doc/html/annotated.html3
-rw-r--r--doc/html/anytun_8cpp.html24
-rw-r--r--doc/html/authAlgo_8cpp.html2
-rw-r--r--doc/html/authAlgo_8h-source.html2
-rw-r--r--doc/html/authAlgo_8h.html2
-rw-r--r--doc/html/buffer_8cpp.html2
-rw-r--r--doc/html/buffer_8h-source.html2
-rw-r--r--doc/html/buffer_8h.html2
-rw-r--r--doc/html/classAesIcmCypher-members.html2
-rw-r--r--doc/html/classAesIcmCypher.html2
-rw-r--r--doc/html/classAuthAlgo-members.html2
-rw-r--r--doc/html/classAuthAlgo.html2
-rw-r--r--doc/html/classBuffer-members.html2
-rw-r--r--doc/html/classBuffer.html2
-rw-r--r--doc/html/classCommunicatingSocket-members.html2
-rw-r--r--doc/html/classCommunicatingSocket.html2
-rw-r--r--doc/html/classCondition-members.html2
-rw-r--r--doc/html/classCondition.html2
-rw-r--r--doc/html/classCypher-members.html2
-rw-r--r--doc/html/classCypher.html2
-rw-r--r--doc/html/classHmacAuthAlgo-members.html2
-rw-r--r--doc/html/classHmacAuthAlgo.html2
-rw-r--r--doc/html/classKeyDerivation-members.html2
-rw-r--r--doc/html/classKeyDerivation.html2
-rw-r--r--doc/html/classLock-members.html2
-rw-r--r--doc/html/classLock.html2
-rw-r--r--doc/html/classLog-members.html2
-rw-r--r--doc/html/classLog.html2
-rw-r--r--doc/html/classLogStringBuilder-members.html2
-rw-r--r--doc/html/classLogStringBuilder.html2
-rw-r--r--doc/html/classLog_1_1instanceCleaner-members.html2
-rw-r--r--doc/html/classLog_1_1instanceCleaner.html2
-rw-r--r--doc/html/classMutex-members.html2
-rw-r--r--doc/html/classMutex.html2
-rw-r--r--doc/html/classNullAuthAlgo-members.html2
-rw-r--r--doc/html/classNullAuthAlgo.html2
-rw-r--r--doc/html/classNullCypher-members.html2
-rw-r--r--doc/html/classNullCypher.html2
-rw-r--r--doc/html/classOptions-members.html2
-rw-r--r--doc/html/classOptions.html2
-rw-r--r--doc/html/classPacket-members.html2
-rw-r--r--doc/html/classPacket.html2
-rw-r--r--doc/html/classPacketSource-members.html2
-rw-r--r--doc/html/classPacketSource.html2
-rw-r--r--doc/html/classSemaphore-members.html2
-rw-r--r--doc/html/classSemaphore.html2
-rw-r--r--doc/html/classSeqWindow-members.html2
-rw-r--r--doc/html/classSeqWindow.html2
-rw-r--r--doc/html/classSigHupHandler-members.html2
-rw-r--r--doc/html/classSigHupHandler.html2
-rw-r--r--doc/html/classSigIntHandler-members.html2
-rw-r--r--doc/html/classSigIntHandler.html2
-rw-r--r--doc/html/classSigQuitHandler-members.html2
-rw-r--r--doc/html/classSigQuitHandler.html2
-rw-r--r--doc/html/classSigTermHandler-members.html2
-rw-r--r--doc/html/classSigTermHandler.html2
-rw-r--r--doc/html/classSigUsr1Handler-members.html2
-rw-r--r--doc/html/classSigUsr1Handler.html2
-rw-r--r--doc/html/classSigUsr2Handler-members.html2
-rw-r--r--doc/html/classSigUsr2Handler.html2
-rw-r--r--doc/html/classSignalController-members.html2
-rw-r--r--doc/html/classSignalController.html2
-rw-r--r--doc/html/classSignalHandler-members.html2
-rw-r--r--doc/html/classSignalHandler.html2
-rw-r--r--doc/html/classSocket-members.html2
-rw-r--r--doc/html/classSocket.html2
-rw-r--r--doc/html/classSocketException-members.html2
-rw-r--r--doc/html/classSocketException.html2
-rw-r--r--doc/html/classTCPServerSocket-members.html2
-rw-r--r--doc/html/classTCPServerSocket.html2
-rw-r--r--doc/html/classTCPSocket-members.html2
-rw-r--r--doc/html/classTCPSocket.html2
-rw-r--r--doc/html/classTunDevice-members.html2
-rw-r--r--doc/html/classTunDevice.html2
-rw-r--r--doc/html/classUDPPacketSource-members.html2
-rw-r--r--doc/html/classUDPPacketSource.html2
-rw-r--r--doc/html/classUDPSocket-members.html2
-rw-r--r--doc/html/classUDPSocket.html2
-rw-r--r--doc/html/classsatp_1_1SATP-members.html2
-rw-r--r--doc/html/classsatp_1_1SATP.html2
-rw-r--r--doc/html/cypher_8cpp.html2
-rw-r--r--doc/html/cypher_8h-source.html2
-rw-r--r--doc/html/cypher_8h.html2
-rw-r--r--doc/html/datatypes_8h-source.html2
-rw-r--r--doc/html/datatypes_8h.html2
-rw-r--r--doc/html/files.html4
-rw-r--r--doc/html/functions.html2
-rw-r--r--doc/html/functions_0x61.html2
-rw-r--r--doc/html/functions_0x62.html2
-rw-r--r--doc/html/functions_0x63.html2
-rw-r--r--doc/html/functions_0x64.html2
-rw-r--r--doc/html/functions_0x65.html2
-rw-r--r--doc/html/functions_0x66.html2
-rw-r--r--doc/html/functions_0x67.html2
-rw-r--r--doc/html/functions_0x68.html2
-rw-r--r--doc/html/functions_0x69.html2
-rw-r--r--doc/html/functions_0x6a.html2
-rw-r--r--doc/html/functions_0x6b.html2
-rw-r--r--doc/html/functions_0x6c.html2
-rw-r--r--doc/html/functions_0x6d.html2
-rw-r--r--doc/html/functions_0x6e.html2
-rw-r--r--doc/html/functions_0x6f.html15
-rw-r--r--doc/html/functions_0x70.html2
-rw-r--r--doc/html/functions_0x72.html2
-rw-r--r--doc/html/functions_0x73.html6
-rw-r--r--doc/html/functions_0x74.html2
-rw-r--r--doc/html/functions_0x75.html2
-rw-r--r--doc/html/functions_0x77.html2
-rw-r--r--doc/html/functions_0x7e.html2
-rw-r--r--doc/html/functions_func.html2
-rw-r--r--doc/html/functions_func_0x62.html2
-rw-r--r--doc/html/functions_func_0x63.html2
-rw-r--r--doc/html/functions_func_0x64.html2
-rw-r--r--doc/html/functions_func_0x65.html2
-rw-r--r--doc/html/functions_func_0x67.html2
-rw-r--r--doc/html/functions_func_0x68.html2
-rw-r--r--doc/html/functions_func_0x69.html2
-rw-r--r--doc/html/functions_func_0x6a.html2
-rw-r--r--doc/html/functions_func_0x6b.html2
-rw-r--r--doc/html/functions_func_0x6c.html2
-rw-r--r--doc/html/functions_func_0x6d.html2
-rw-r--r--doc/html/functions_func_0x6f.html21
-rw-r--r--doc/html/functions_func_0x70.html2
-rw-r--r--doc/html/functions_func_0x72.html2
-rw-r--r--doc/html/functions_func_0x73.html6
-rw-r--r--doc/html/functions_func_0x74.html2
-rw-r--r--doc/html/functions_func_0x75.html2
-rw-r--r--doc/html/functions_func_0x77.html2
-rw-r--r--doc/html/functions_func_0x7e.html2
-rw-r--r--doc/html/functions_rela.html2
-rw-r--r--doc/html/functions_type.html2
-rw-r--r--doc/html/functions_vars.html2
-rw-r--r--doc/html/globals.html4
-rw-r--r--doc/html/globals_defs.html2
-rw-r--r--doc/html/globals_enum.html2
-rw-r--r--doc/html/globals_eval.html2
-rw-r--r--doc/html/globals_func.html4
-rw-r--r--doc/html/globals_type.html2
-rw-r--r--doc/html/globals_vars.html2
-rw-r--r--doc/html/hierarchy.html3
-rw-r--r--doc/html/keyDerivation_8cpp.html2
-rw-r--r--doc/html/keyDerivation_8h-source.html2
-rw-r--r--doc/html/keyDerivation_8h.html2
-rw-r--r--doc/html/log_8cpp.html2
-rw-r--r--doc/html/log_8h-source.html2
-rw-r--r--doc/html/log_8h.html2
-rw-r--r--doc/html/main.html2
-rw-r--r--doc/html/namespaces.html3
-rw-r--r--doc/html/namespacesatp.html2
-rw-r--r--doc/html/namespacescapy_1_1_5.html2
-rw-r--r--doc/html/namespacestd.html2
-rw-r--r--doc/html/options_8cpp.html2
-rw-r--r--doc/html/options_8h-source.html2
-rw-r--r--doc/html/options_8h.html2
-rw-r--r--doc/html/packetSource_8cpp.html2
-rw-r--r--doc/html/packetSource_8h-source.html2
-rw-r--r--doc/html/packetSource_8h.html2
-rw-r--r--doc/html/packet_8cpp.html2
-rw-r--r--doc/html/packet_8h-source.html2
-rw-r--r--doc/html/packet_8h.html2
-rw-r--r--doc/html/satp_8py.html2
-rw-r--r--doc/html/seqWindow_8cpp.html2
-rw-r--r--doc/html/seqWindow_8h-source.html2
-rw-r--r--doc/html/seqWindow_8h.html2
-rw-r--r--doc/html/signalController_8cpp.html2
-rw-r--r--doc/html/signalController_8h-source.html2
-rw-r--r--doc/html/signalController_8h.html2
-rw-r--r--doc/html/structPacket_1_1HeaderStruct-members.html2
-rw-r--r--doc/html/structPacket_1_1HeaderStruct.html2
-rw-r--r--doc/html/structParam-members.html2
-rw-r--r--doc/html/structParam.html2
-rw-r--r--doc/html/threadUtils_8hpp-source.html2
-rw-r--r--doc/html/threadUtils_8hpp.html2
-rw-r--r--doc/html/tree.html5
-rw-r--r--doc/html/tunDevice_8cpp.html2
-rw-r--r--doc/html/tunDevice_8h-source.html2
-rw-r--r--doc/html/tunDevice_8h.html2
-rw-r--r--doc/latex/annotated.tex1
-rw-r--r--doc/latex/anytun_8cpp.tex7
-rw-r--r--doc/latex/doxygen.sty4
-rw-r--r--doc/latex/files.tex2
-rw-r--r--doc/latex/hierarchy.tex1
-rw-r--r--doc/latex/namespaces.tex1
-rw-r--r--doc/latex/refman.tex6
-rw-r--r--syncSocket.cpp37
-rw-r--r--syncSocket.h24
332 files changed, 29530 insertions, 199 deletions
diff --git a/Makefile b/Makefile
index e659660..7c77012 100644
--- a/Makefile
+++ b/Makefile
@@ -1,9 +1,13 @@
C = gcc
CFLAGS = -g -Wall
+CFLAGS += -DSOCKETS_NAMESPACE=sockets
+CFLAGS += -DSOCKETS_NAMESPACE_STR='"sockets"'
C++ = g++
CCFLAGS = -g -Wall
+CCFLAGS += -DSOCKETS_NAMESPACE=sockets
+CCFLAGS += -DSOCKETS_NAMESPACE_STR='"sockets"'
LD = g++
-LDFLAGS = -g -Wall -O2 -ldl -lpthread -lgcrypt
+LDFLAGS = -g -Wall -O2 -ldl -lpthread -lgcrypt -lssl
OPENVPNDEPS = openvpn/tun.o \
openvpn/error.o \
@@ -29,6 +33,17 @@ OPENVPNDEPS = openvpn/tun.o \
openvpn/shaper.o \
openvpn/fragment.o
+SOCKETDEPS = Sockets/libSockets.a
+
+#Sockets/TcpSocket.o \
+# Sockets/Socket.o \
+# Sockets/Thread.o \
+# Sockets/SocketHandler.o \
+# Sockets/Ipv4Address.o \
+# Sockets/Mutex.o \
+# Sockets/SSLInitializer.o
+
+
OBJS = anytun.o \
tunDevice.o \
packetSource.o \
@@ -43,10 +58,12 @@ OBJS = anytun.o \
PracticalSocket.o \
router.o \
signalController.o \
+ syncSocket.o \
log.o \
options.o \
seqWindow.o \
- $(OPENVPNDEPS)
+ $(OPENVPNDEPS) \
+ $(SOCKETDEPS)
EXECUTABLE = anytun
@@ -76,6 +93,9 @@ authAlgo.o: authAlgo.cpp authAlgo.h buffer.h
keyDerivation.o: keyDerivation.cpp keyDerivation.h
$(C++) $(CCFLAGS) $< -c
+syncSocket.o: syncSocket.cpp syncSocket.h
+ $(C++) $(CCFLAGS) $< -c
+
signalController.o: signalController.cpp signalController.h
$(C++) $(CCFLAGS) $< -c
diff --git a/README b/README
index 392e1bf..e342f36 100644
--- a/README
+++ b/README
@@ -1,7 +1,11 @@
+Dependencies
+============
+
+libgcrypt11-dev
+libssl-dev (Openssl)
+
Building
========
-* install libgcrypt
-* install libgcrypt11-dev
* ./configure
* make
diff --git a/Sockets/Ajp13Socket.cpp b/Sockets/Ajp13Socket.cpp
new file mode 100644
index 0000000..57755f0
--- /dev/null
+++ b/Sockets/Ajp13Socket.cpp
@@ -0,0 +1,404 @@
+/**
+ ** \file Ajp13Socket.cpp
+ ** \date 2007-10-05
+ ** \author grymse@alhem.net
+**/
+/*
+Copyright (C) 2007 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 _MSC_VER
+#pragma warning(disable:4786)
+#endif
+#include "Ajp13Socket.h"
+#include "ajp13.h"
+#include "HttpRequest.h"
+#include "HttpResponse.h"
+#include "IFile.h"
+#include "Utility.h"
+
+#ifdef SOCKETS_NAMESPACE
+namespace SOCKETS_NAMESPACE {
+#endif
+
+#ifdef _DEBUG
+#define DEB(x) x
+#else
+#define DEB(x)
+#endif
+
+
+// --------------------------------------------------------------------------------------
+Ajp13Socket::Ajp13Socket(ISocketHandler& h) : AjpBaseSocket(h)
+, m_body_size_left(0)
+, m_res_file(NULL)
+{
+}
+
+
+// --------------------------------------------------------------------------------------
+void Ajp13Socket::OnHeader( short id, short len )
+{
+ if (id != 0x1234)
+ {
+ fprintf(stderr, "ABORT: bad packet id: %x\n", id);
+ SetCloseAndDelete();
+ }
+ else
+ {
+ DEB(fprintf(stderr, "Packet size: %d bytes\n", len);)
+ }
+}
+
+
+// --------------------------------------------------------------------------------------
+void Ajp13Socket::ReceiveBody(const char *buf, size_t sz)
+{
+ if (sz - 2 > m_body_size_left)
+ {
+ fprintf(stderr, "More body data received than expected\n");
+ SetCloseAndDelete();
+ return;
+ }
+
+ m_req.Write( buf + 2, sz - 2 );
+ m_body_size_left -= sz - 2;
+
+ // request more body data
+ if (m_body_size_left)
+ {
+ int ptr = 4;
+ char msg[100];
+ msg[0] = 'A';
+ msg[1] = 'B';
+
+// reply codes
+// 0x3 Send Body Chunk
+// 0x4 Send Headers
+// 0x5 End Response
+// 0x6 Get Body Chunk <------
+// 0x9 CPong Reply
+
+ put_byte(msg, ptr, 0x06); // GET_BODY_CHUNK;
+ put_integer(msg, ptr, 1000); // request 1000 bytes
+
+ short len = htons( ptr - 4 );
+ memcpy( msg + 2, &len, 2 );
+
+ SendBuf( msg, ptr );
+ return;
+ }
+
+ // Close
+ m_req.CloseBody();
+
+ // no more body data left to read - execute
+ Execute();
+
+}
+
+
+// --------------------------------------------------------------------------------------
+void Ajp13Socket::ReceiveForwardRequest( const char *buf, size_t sz )
+{
+ //
+ int ptr = 0;
+
+ get_byte(buf, ptr); // skip first byte: prefix_code
+ unsigned char method = get_byte(buf, ptr);
+ std::string protocol = get_string(buf, ptr);
+ std::string req_uri = get_string(buf, ptr);
+ std::string remote_addr = get_string(buf, ptr);
+ std::string remote_host = get_string(buf, ptr);
+ std::string server_name = get_string(buf, ptr);
+ short server_port = get_integer(buf, ptr);
+ bool is_ssl = get_boolean(buf, ptr);
+
+ std::string method_str = Utility::l2string( method );
+ std::map<int, std::string>::const_iterator it = Init.Method.find( method );
+ if (it != Init.Method.end())
+ {
+ method_str = it -> second;
+ }
+ m_req.SetHttpMethod( method_str );
+ m_req.SetHttpVersion( protocol );
+ m_req.SetUri( req_uri );
+ m_req.SetRemoteAddr( remote_addr );
+ m_req.SetRemoteHost( remote_host );
+ m_req.SetServerName( server_name );
+ m_req.SetServerPort( server_port );
+ m_req.SetIsSsl( is_ssl );
+
+ // Get Headers
+ short num_headers = get_integer(buf, ptr);
+ for (int i = 0; i < num_headers; i++)
+ {
+ std::string key;
+ switch ( (unsigned char)buf[ptr]) // 0xa0
+ {
+ case 0xa0:
+ {
+ unsigned short x = (unsigned short)get_integer(buf, ptr);
+ std::map<int, std::string>::const_iterator it;
+ if ( (it = Init.Header.find(x)) != Init.Header.end())
+ {
+ key = it -> second;
+ }
+ else
+ {
+ fprintf(stderr, "Unknown header key value: %x\n", x);
+ SetCloseAndDelete();
+ }
+ }
+ break;
+
+ default: // string
+ key = get_string(buf, ptr);
+ }
+ if (Utility::ToLower(key) == "cookie" || Utility::ToLower(key) == "cookie2")
+ m_req.AddCookie(get_string(buf, ptr));
+ else
+ m_req.SetHeader(key, get_string(buf, ptr));
+ } // for
+
+ // size left to read from web server
+ m_body_size_left = m_req.ContentLength();
+
+ // Get Attributes
+ while ( (unsigned char)buf[ptr] != 0xff)
+ {
+ std::string key;
+ unsigned char code = buf[ptr++];
+ switch ( code)
+ {
+ case 10: // req_attribute, attribute name follow
+ key = get_string(buf, ptr);
+ break;
+ default:
+ {
+ std::map<int, std::string>::const_iterator it = Init.Attribute.find( code );
+ if (it != Init.Attribute.end())
+ {
+ key = it -> second;
+ }
+ else
+ {
+ fprintf(stderr, "Unknown attribute key: 0x%02x\n", buf[ptr]);
+ SetCloseAndDelete();
+ }
+ }
+ }
+ m_req.SetAttribute(key, get_string(buf, ptr));
+ } // while
+
+ // execute at once if no body data
+ if (!m_body_size_left)
+ {
+ Execute();
+ }
+ else
+ {
+ // open temporary file for body data
+ m_req.InitBody( m_body_size_left );
+ }
+}
+
+
+// --------------------------------------------------------------------------------------
+void Ajp13Socket::ReceiveShutdown( const char *buf, size_t sz )
+{
+}
+
+
+// --------------------------------------------------------------------------------------
+void Ajp13Socket::ReceivePing( const char *buf, size_t sz )
+{
+}
+
+
+// --------------------------------------------------------------------------------------
+void Ajp13Socket::ReceiveCPing( const char *buf, size_t sz )
+{
+}
+
+
+// --------------------------------------------------------------------------------------
+void Ajp13Socket::Execute()
+{
+ // parse form data / query_string and cookie header if available
+ m_req.ParseBody();
+
+ // prepare page
+ OnExec( m_req );
+
+}
+
+
+// --------------------------------------------------------------------------------------
+void Ajp13Socket::Respond(const HttpResponse& res)
+{
+ char msg[8192];
+ msg[0] = 'A';
+ msg[1] = 'B';
+
+// reply codes
+// 0x3 Send Body Chunk
+// 0x4 Send Headers
+// 0x5 End Response
+// 0x6 Get Body Chunk
+// 0x9 CPong Reply
+
+ // check content length
+ if (!res.ContentLength() && res.GetFile().size())
+ {
+// res.SetContentLength( res.GetFile().size() );
+ }
+
+ // Send Headers
+ {
+ int ptr = 4;
+ put_byte(msg, ptr, 0x04); // send headers
+ put_integer(msg, ptr, res.HttpStatusCode() );
+ put_string(msg, ptr, res.HttpStatusMsg() );
+ put_integer(msg, ptr, (short)res.Headers().size() );
+ for (std::map<std::string, std::string>::const_iterator it = res.Headers().begin(); it != res.Headers().end(); ++it)
+ {
+ std::map<std::string, int>::const_iterator it2 = Init.ResponseHeader.find( it -> first );
+ if (it2 != Init.ResponseHeader.end())
+ {
+ put_integer(msg, ptr, it2 -> second);
+ }
+ else
+ {
+ put_string(msg, ptr, it -> first);
+ }
+ put_string(msg, ptr, it -> second);
+ }
+ std::list<std::string> vec = res.CookieNames();
+ {
+ for (std::list<std::string>::iterator it = vec.begin(); it != vec.end(); it++)
+ {
+ std::map<std::string, int>::const_iterator it2 = Init.ResponseHeader.find( "set-cookie" );
+ if (it2 != Init.ResponseHeader.end())
+ {
+ put_integer(msg, ptr, it2 -> second);
+ }
+ else
+ {
+ put_string(msg, ptr, "set-cookie");
+ }
+ put_string(msg, ptr, res.Cookie(*it) );
+ }
+ }
+
+ short len = htons( ptr - 4 );
+ memcpy( msg + 2, &len, 2 );
+
+ SendBuf( msg, ptr );
+ }
+ m_res_file = &res.GetFile();
+ // Send Body Chunk
+ OnTransferLimit();
+}
+
+
+// --------------------------------------------------------------------------------------
+void Ajp13Socket::OnTransferLimit()
+{
+ char msg[8192];
+ msg[0] = 'A';
+ msg[1] = 'B';
+
+ // Send Body Chunk
+ size_t n = m_res_file -> fread(msg + 7, 1, 8100);
+ while (n > 0)
+ {
+ int ptr = 4;
+ put_byte(msg, ptr, 0x03); // send body chunk
+ put_integer(msg, ptr, (short)n);
+ ptr += (int)n;
+
+ short len = htons( ptr - 4 );
+ memcpy( msg + 2, &len, 2 );
+
+ SendBuf( msg, ptr );
+ if (GetOutputLength() > 1)
+ {
+ SetTransferLimit( 1 );
+ break;
+ }
+
+ //
+ n = m_res_file -> fread(msg + 7, 1, 8100);
+ }
+ if (!GetOutputLength()) // all body data sent and no data in output buffer - send end response
+ {
+ // End Response
+ int ptr = 4;
+ put_byte(msg, ptr, 0x05); // end response
+ put_boolean(msg, ptr, false); // reuse
+ /*
+ don't reuse
+ - but with m_req.Reset() and res.Reset() it should be possible
+ - also reset any AjpBaseSocket/Ajp13Socket specific states
+ */
+
+ short len = htons( ptr - 4 );
+ memcpy( msg + 2, &len, 2 );
+
+ SendBuf( msg, ptr );
+ }
+}
+
+
+// --------------------------------------------------------------------------------------
+void Ajp13Socket::OnPacket( const char *buf, size_t sz )
+{
+ DEB(fprintf(stderr, "OnPacket: %d bytes, code 0x%02x %02x %02x %02x\n", sz, *buf, buf[1], buf[2], buf[3]);)
+
+ // check body size left to read, if non-zero packet is body data
+ if (m_body_size_left) // must be a body packet
+ {
+ ReceiveBody(buf, sz);
+ return;
+ }
+ switch (*buf)
+ {
+ case 0x2: // Forward Request
+ ReceiveForwardRequest(buf, sz);
+ break;
+ case 0x7: // Shutdown
+ ReceiveShutdown(buf, sz);
+ break;
+ case 0x8: // Ping
+ ReceivePing(buf, sz);
+ break;
+ case 0xa: // CPing
+ ReceiveCPing(buf, sz);
+ break;
+ default:
+ fprintf(stderr, "Unknown packet type: 0x%02x\n", *buf);
+ SetCloseAndDelete();
+ }
+
+}
+
+
+#ifdef SOCKETS_NAMESPACE
+} // namespace SOCKETS_NAMESPACE {
+#endif
+
+
diff --git a/Sockets/Ajp13Socket.h b/Sockets/Ajp13Socket.h
new file mode 100644
index 0000000..3da5be7
--- /dev/null
+++ b/Sockets/Ajp13Socket.h
@@ -0,0 +1,69 @@
+/**
+ ** \file Ajp13Socket.h
+ ** \date 2007-10-05
+ ** \author grymse@alhem.net
+**/
+/*
+Copyright (C) 2007 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.
+*/
+#ifndef _SOCKETS_Ajp13Socket_H
+#define _SOCKETS_Ajp13Socket_H
+
+#include "AjpBaseSocket.h"
+#include "HttpRequest.h"
+#include "IHttpServer.h"
+
+#ifdef SOCKETS_NAMESPACE
+namespace SOCKETS_NAMESPACE {
+#endif
+
+
+class HttpResponse;
+
+class Ajp13Socket : public AjpBaseSocket, public IHttpServer
+{
+public:
+ Ajp13Socket(ISocketHandler& h);
+
+ void OnHeader( short id, short len );
+ void OnPacket( const char *buf, size_t sz );
+
+ // implements IHttpServer::Respond
+ void Respond(const HttpResponse& res);
+
+ void OnTransferLimit();
+
+private:
+ void ReceiveBody( const char *buf, size_t sz );
+ void ReceiveForwardRequest( const char *buf, size_t sz );
+ void ReceiveShutdown( const char *buf, size_t sz );
+ void ReceivePing( const char *buf, size_t sz );
+ void ReceiveCPing( const char *buf, size_t sz );
+ void Execute();
+ //
+ size_t m_body_size_left;
+ HttpRequest m_req;
+ const IFile *m_res_file;
+};
+
+
+#ifdef SOCKETS_NAMESPACE
+} // namespace SOCKETS_NAMESPACE {
+#endif
+
+#endif // _SOCKETS_Ajp13Socket_H
+
diff --git a/Sockets/AjpBaseSocket.cpp b/Sockets/AjpBaseSocket.cpp
new file mode 100644
index 0000000..3b54dd0
--- /dev/null
+++ b/Sockets/AjpBaseSocket.cpp
@@ -0,0 +1,258 @@
+/**
+ ** \file AjpBaseSocket.cpp
+ ** \date 2007-10-05
+ ** \author grymse@alhem.net
+**/
+/*
+Copyright (C) 2007 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 _MSC_VER
+#pragma warning(disable:4786)
+#endif
+#include "AjpBaseSocket.h"
+#include "ajp13.h"
+
+#ifdef SOCKETS_NAMESPACE
+namespace SOCKETS_NAMESPACE {
+#endif
+
+#ifdef _DEBUG
+#define DEB(x) x
+#else
+#define DEB(x)
+#endif
+
+
+// ---------------------------------------------------------------------------
+AjpBaseSocket::Initializer AjpBaseSocket::Init;
+
+
+// ---------------------------------------------------------------------------
+AjpBaseSocket::Initializer::Initializer()
+{
+
+ Header[HTTP_REQUEST_ACCEPT] = "accept";
+ Header[HTTP_REQUEST_ACCEPT_CHARSET] = "accept-charset";
+ Header[HTTP_REQUEST_ACCEPT_ENCODING] = "accept-encoding";
+ Header[HTTP_REQUEST_ACCEPT_LANGUAGE] = "accept-language";
+ Header[HTTP_REQUEST_AUTHORIZATION] = "authorization";
+ Header[HTTP_REQUEST_CONNECTION] = "connection";
+ Header[HTTP_REQUEST_CONTENT_TYPE] = "content-type";
+ Header[HTTP_REQUEST_CONTENT_LENGTH] = "content-length";
+ Header[HTTP_REQUEST_COOKIE] = "cookie";
+ Header[HTTP_REQUEST_COOKIE2] = "cookie2";
+ Header[HTTP_REQUEST_HOST] = "host";
+ Header[HTTP_REQUEST_PRAGMA] = "pragma";
+ Header[HTTP_REQUEST_REFERER] = "referer";
+ Header[HTTP_REQUEST_USER_AGENT] = "user-agent";
+
+ Method[HTTP_METHOD_OPTIONS] = "OPTIONS";
+ Method[HTTP_METHOD_GET] = "GET";
+ Method[HTTP_METHOD_HEAD] = "HEAD";
+ Method[HTTP_METHOD_POST] = "POST";
+ Method[HTTP_METHOD_PUT] = "PUT";
+ Method[HTTP_METHOD_DELETE] = "DELETE";
+ Method[HTTP_METHOD_TRACE] = "TRACE";
+ Method[HTTP_METHOD_PROPFIND] = "PROPFIND";
+ Method[HTTP_METHOD_PROPPATCH] = "PROPPATCH";
+ Method[HTTP_METHOD_MKCOL] = "MKCOL";
+ Method[HTTP_METHOD_COPY] = "COPY";
+ Method[HTTP_METHOD_MOVE] = "MOVE";
+ Method[HTTP_METHOD_LOCK] = "LOCK";
+ Method[HTTP_METHOD_UNLOCK] = "UNLOCK";
+ Method[HTTP_METHOD_ACL] = "ACL";
+ Method[HTTP_METHOD_REPORT] = "REPORT";
+ Method[HTTP_METHOD_VERSION_CONTROL] = "VERSION_CONTROL"; // with a dash "VERSION-CONTROL"
+ Method[HTTP_METHOD_CHECKIN] = "CHECKIN";
+ Method[HTTP_METHOD_CHECKOUT] = "CHECKOUT";
+ Method[HTTP_METHOD_UNCHECKOUT] = "UNCHECKOUT";
+ Method[HTTP_METHOD_SEARCH] = "SEARCH";
+ Method[HTTP_METHOD_MKWORKSPACE] = "MKWORKSPACE";
+ Method[HTTP_METHOD_UPDATE] = "UPDATE";
+ Method[HTTP_METHOD_LABEL] = "LABEL";
+ Method[HTTP_METHOD_MERGE] = "MERGE";
+ Method[HTTP_METHOD_BASELINE_CONTROL] = "BASELINE_CONTROL";
+ Method[HTTP_METHOD_MKACTIVITY] = "MKACTIVITY";
+
+ Attribute[ATTR_CONTEXT] = "context";
+ Attribute[ATTR_SERVLET_PATH] = "servlet_path";
+ Attribute[ATTR_REMOTE_USER] = "remote_user";
+ Attribute[ATTR_AUTH_TYPE] = "auth_type";
+ Attribute[ATTR_QUERY_STRING] = "query_string";
+ Attribute[ATTR_ROUTE] = "route";
+ Attribute[ATTR_SSL_CERT] = "ssl_cert";
+ Attribute[ATTR_SSL_CIPHER] = "ssl_cipher";
+ Attribute[ATTR_SSL_SESSION] = "ssl_session";
+ Attribute[ATTR_SSL_KEY_SIZE] = "ssl_key_size";
+ Attribute[ATTR_SECRET] = "secret";
+ Attribute[ATTR_STORED_METHOD] = "stored_method";
+
+ ResponseHeader["content-type"] = 0xa001;
+ ResponseHeader["content-language"] = 0xa002;
+ ResponseHeader["content-length"] = 0xa003;
+ ResponseHeader["date"] = 0xa004;
+ ResponseHeader["last-modified"] = 0xa005;
+ ResponseHeader["location"] = 0xa006;
+ ResponseHeader["set-cookie"] = 0xa007;
+ ResponseHeader["set-cookie2"] = 0xa008;
+ ResponseHeader["servlet-engine"] = 0xa009;
+ ResponseHeader["status"] = 0xa00a;
+ ResponseHeader["www-authenticate"] = 0xa00b;
+}
+
+
+// ---------------------------------------------------------------------------
+AjpBaseSocket::AjpBaseSocket(ISocketHandler& h) : TcpSocket(h)
+, m_state(0)
+, m_length(4)
+, m_ptr(0)
+{
+}
+
+
+// ---------------------------------------------------------------------------
+void AjpBaseSocket::OnRawData(const char *buf, size_t sz)
+{
+DEB(fprintf(stderr, "OnRawData: %d bytes\n", sz);)
+ size_t ptr = 0;
+ while (true)
+ {
+ size_t left = sz - ptr;
+DEB(fprintf(stderr, " left: %d bytes\n", left);
+fprintf(stderr, " state: %d\n", m_state);)
+ switch (m_state)
+ {
+ case 0:
+ {
+ size_t missing = m_length - m_ptr;
+ short len = (short)(missing < left ? missing : left);
+ memcpy(m_message + m_ptr, buf + ptr, len);
+ m_ptr += len;
+ ptr += len;
+ if (m_ptr < m_length)
+ {
+ return; // read more
+ }
+ int p = 0;
+ short id = get_integer(m_message, p);
+ short length = get_integer(m_message, p);
+ OnHeader(id, length);
+ m_state = 1;
+ m_length = length;
+ m_ptr = 0; // bytes in m_message
+ }
+ break;
+ case 1:
+ {
+ size_t missing = m_length - m_ptr;
+ short len = (short)(missing < left ? missing : left);
+ memcpy(m_message + m_ptr, buf + ptr, len);
+ m_ptr += len;
+ ptr += len;
+ if (m_ptr < m_length)
+ {
+ return; // read more
+ }
+ OnPacket(m_message, m_ptr);
+ m_state = 0;
+ m_length = 4;
+ m_ptr = 0;
+ }
+ break;
+ }
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+unsigned char AjpBaseSocket::get_byte(const char *buf, int& ptr)
+{
+ return (unsigned char)buf[ptr++];
+}
+
+
+// ---------------------------------------------------------------------------
+bool AjpBaseSocket::get_boolean(const char *buf, int& ptr)
+{
+ return ( (unsigned char)buf[ptr++] & 1) == 1 ? true : false;
+}
+
+
+// ---------------------------------------------------------------------------
+short AjpBaseSocket::get_integer(const char *buf, int& ptr)
+{
+ short n;
+ memcpy(&n, buf + ptr, 2);
+ ptr += 2;
+ return ntohs(n);
+}
+
+
+// ---------------------------------------------------------------------------
+std::string AjpBaseSocket::get_string(const char *buf, int& ptr)
+{
+ short len = get_integer(buf, ptr);
+ if (len != -1)
+ {
+ std::string tmp = buf + ptr;
+ ptr += len;
+ ptr++; // skip trailing 0x0
+ tmp.resize(len);
+ return tmp;
+ }
+ return "";
+}
+
+
+// ---------------------------------------------------------------------------
+void AjpBaseSocket::put_byte(char *buf, int& ptr, unsigned char zz)
+{
+ buf[ptr++] = zz;
+}
+
+
+// ---------------------------------------------------------------------------
+void AjpBaseSocket::put_boolean(char *buf, int& ptr, bool zz)
+{
+ buf[ptr++] = zz ? 1 : 0;
+}
+
+
+// ---------------------------------------------------------------------------
+void AjpBaseSocket::put_integer(char *buf, int& ptr, short zz)
+{
+ short tmp = htons(zz);
+ memcpy(buf + ptr, &tmp, 2);
+ ptr += 2;
+}
+
+
+// ---------------------------------------------------------------------------
+void AjpBaseSocket::put_string(char *buf, int& ptr, const std::string& zz)
+{
+ put_integer(buf, ptr, (short)zz.size() );
+ memcpy(buf + ptr, zz.c_str(), zz.size());
+ ptr += (int)zz.size();
+ put_byte(buf, ptr, 0);
+}
+
+
+#ifdef SOCKETS_NAMESPACE
+} // namespace SOCKETS_NAMESPACE {
+#endif
+
+
diff --git a/Sockets/AjpBaseSocket.h b/Sockets/AjpBaseSocket.h
new file mode 100644
index 0000000..222df70
--- /dev/null
+++ b/Sockets/AjpBaseSocket.h
@@ -0,0 +1,83 @@
+/**
+ ** \file AjpBaseSocket.h
+ ** \date 2007-10-05
+ ** \author grymse@alhem.net
+**/
+/*
+Copyright (C) 2007 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.
+*/
+#ifndef _SOCKETS_AjpBaseSocket_H
+#define _SOCKETS_AjpBaseSocket_H
+
+#include "TcpSocket.h"
+#include <map>
+
+#ifdef SOCKETS_NAMESPACE
+namespace SOCKETS_NAMESPACE {
+#endif
+
+class AjpBaseSocket : public TcpSocket
+{
+ class Initializer
+ {
+ public:
+ Initializer();
+ virtual ~Initializer() {}
+
+ std::map<int, std::string> Method;
+ std::map<int, std::string> Header;
+ std::map<int, std::string> Attribute;
+
+ std::map<std::string, int> ResponseHeader;
+
+ };
+
+public:
+ AjpBaseSocket(ISocketHandler& h);
+
+ void OnRawData(const char *buf, size_t sz);
+
+ virtual void OnHeader( short id, short len ) = 0;
+ virtual void OnPacket( const char *buf, size_t sz ) = 0;
+
+protected:
+ unsigned char get_byte(const char *buf, int& ptr);
+ bool get_boolean(const char *buf, int& ptr);
+ short get_integer(const char *buf, int& ptr);
+ std::string get_string(const char *buf, int& ptr);
+
+ void put_byte(char *buf, int& ptr, unsigned char zz);
+ void put_boolean(char *buf, int& ptr, bool zz);
+ void put_integer(char *buf, int& ptr, short zz);
+ void put_string(char *buf, int& ptr, const std::string& zz);
+
+ static Initializer Init;
+
+private:
+ int m_state;
+ int m_length;
+ int m_ptr;
+ char m_message[8192];
+};
+
+
+#ifdef SOCKETS_NAMESPACE
+} // namespace SOCKETS_NAMESPACE {
+#endif
+
+#endif // _SOCKETS_AjpBaseSocket_H
+
diff --git a/Sockets/Base64.cpp b/Sockets/Base64.cpp
new file mode 100644
index 0000000..4619756
--- /dev/null
+++ b/Sockets/Base64.cpp
@@ -0,0 +1,272 @@
+/** \file Base64.cpp
+ ** \date 2004-02-13
+ ** \author grymse@alhem.net
+**/
+/*
+Copyright (C) 2004-2007 Anders Hedstrom
+
+This library is made available under the terms of the GNU GPL.
+
+If you would like to use this library in a closed-source application,
+a separate license agreement is available. For information about
+the closed-source license agreement for the C++ sockets library,
+please visit http://www.alhem.net/Sockets/license.html and/or
+email license@alhem.net.
+
+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.
+*/
+#include "Base64.h"
+
+#ifdef SOCKETS_NAMESPACE
+namespace SOCKETS_NAMESPACE {
+#endif
+
+
+const char *Base64::bstr =
+ "ABCDEFGHIJKLMNOPQ"
+ "RSTUVWXYZabcdefgh"
+ "ijklmnopqrstuvwxy"
+ "z0123456789+/";
+
+const char Base64::rstr[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 0, 0, 63,
+ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0, 0, 0, 0, 0,
+ 0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
+ 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 0, 0, 0, 0, 0};
+
+
+Base64::Base64()
+{
+}
+
+
+void Base64::encode(FILE *fil, std::string& output, bool add_crlf)
+{
+ size_t remain;
+ size_t i = 0;
+ size_t o = 0;
+ char input[4];
+
+ output = "";
+ remain = fread(input,1,3,fil);
+ while (remain > 0)
+ {
+ if (add_crlf && o && o % 76 == 0)
+ output += "\n";
+ switch (remain)
+ {
+ case 1:
+ output += bstr[ ((input[i] >> 2) & 0x3f) ];
+ output += bstr[ ((input[i] << 4) & 0x30) ];
+ output += "==";
+ break;
+ case 2:
+ output += bstr[ ((input[i] >> 2) & 0x3f) ];
+ output += bstr[ ((input[i] << 4) & 0x30) + ((input[i + 1] >> 4) & 0x0f) ];
+ output += bstr[ ((input[i + 1] << 2) & 0x3c) ];
+ output += "=";
+ break;
+ default:
+ output += bstr[ ((input[i] >> 2) & 0x3f) ];
+ output += bstr[ ((input[i] << 4) & 0x30) + ((input[i + 1] >> 4) & 0x0f) ];
+ output += bstr[ ((input[i + 1] << 2) & 0x3c) + ((input[i + 2] >> 6) & 0x03) ];
+ output += bstr[ (input[i + 2] & 0x3f) ];
+ }
+ o += 4;
+ //
+ remain = fread(input,1,3,fil);
+ }
+}
+
+
+void Base64::encode(const std::string& str_in, std::string& str_out, bool add_crlf)
+{
+ encode(str_in.c_str(), str_in.size(), str_out, add_crlf);
+}
+
+
+void Base64::encode(const char* input,size_t l,std::string& output, bool add_crlf)
+{
+ size_t i = 0;
+ size_t o = 0;
+
+ output = "";
+ while (i < l)
+ {
+ size_t remain = l - i;
+ if (add_crlf && o && o % 76 == 0)
+ output += "\n";
+ switch (remain)
+ {
+ case 1:
+ output += bstr[ ((input[i] >> 2) & 0x3f) ];
+ output += bstr[ ((input[i] << 4) & 0x30) ];
+ output += "==";
+ break;
+ case 2:
+ output += bstr[ ((input[i] >> 2) & 0x3f) ];
+ output += bstr[ ((input[i] << 4) & 0x30) + ((input[i + 1] >> 4) & 0x0f) ];
+ output += bstr[ ((input[i + 1] << 2) & 0x3c) ];
+ output += "=";
+ break;
+ default:
+ output += bstr[ ((input[i] >> 2) & 0x3f) ];
+ output += bstr[ ((input[i] << 4) & 0x30) + ((input[i + 1] >> 4) & 0x0f) ];
+ output += bstr[ ((input[i + 1] << 2) & 0x3c) + ((input[i + 2] >> 6) & 0x03) ];
+ output += bstr[ (input[i + 2] & 0x3f) ];
+ }
+ o += 4;
+ i += 3;
+ }
+}
+
+
+void Base64::encode(const unsigned char* input,size_t l,std::string& output,bool add_crlf)
+{
+ size_t i = 0;
+ size_t o = 0;
+
+ output = "";
+ while (i < l)
+ {
+ size_t remain = l - i;
+ if (add_crlf && o && o % 76 == 0)
+ output += "\n";
+ switch (remain)
+ {
+ case 1:
+ output += bstr[ ((input[i] >> 2) & 0x3f) ];
+ output += bstr[ ((input[i] << 4) & 0x30) ];
+ output += "==";
+ break;
+ case 2:
+ output += bstr[ ((input[i] >> 2) & 0x3f) ];
+ output += bstr[ ((input[i] << 4) & 0x30) + ((input[i + 1] >> 4) & 0x0f) ];
+ output += bstr[ ((input[i + 1] << 2) & 0x3c) ];
+ output += "=";
+ break;
+ default:
+ output += bstr[ ((input[i] >> 2) & 0x3f) ];
+ output += bstr[ ((input[i] << 4) & 0x30) + ((input[i + 1] >> 4) & 0x0f) ];
+ output += bstr[ ((input[i + 1] << 2) & 0x3c) + ((input[i + 2] >> 6) & 0x03) ];
+ output += bstr[ (input[i + 2] & 0x3f) ];
+ }
+ o += 4;
+ i += 3;
+ }
+}
+
+
+void Base64::decode(const std::string& input,std::string& output)
+{
+ size_t i = 0;
+ size_t l = input.size();
+
+ output = "";
+ while (i < l)
+ {
+ while (i < l && (input[i] == 13 || input[i] == 10))
+ i++;
+ if (i < l)
+ {
+ char b1 = (char)((rstr[(int)input[i]] << 2 & 0xfc) +
+ (rstr[(int)input[i + 1]] >> 4 & 0x03));
+ output += b1;
+ if (input[i + 2] != '=')
+ {
+ char b2 = (char)((rstr[(int)input[i + 1]] << 4 & 0xf0) +
+ (rstr[(int)input[i + 2]] >> 2 & 0x0f));
+ output += b2;
+ }
+ if (input[i + 3] != '=')
+ {
+ char b3 = (char)((rstr[(int)input[i + 2]] << 6 & 0xc0) +
+ rstr[(int)input[i + 3]]);
+ output += b3;
+ }
+ i += 4;
+ }
+ }
+}
+
+
+void Base64::decode(const std::string& input, unsigned char *output, size_t& sz)
+{
+ size_t i = 0;
+ size_t l = input.size();
+ size_t j = 0;
+
+ while (i < l)
+ {
+ while (i < l && (input[i] == 13 || input[i] == 10))
+ i++;
+ if (i < l)
+ {
+ unsigned char b1 = (unsigned char)((rstr[(int)input[i]] << 2 & 0xfc) +
+ (rstr[(int)input[i + 1]] >> 4 & 0x03));
+ if (output)
+ {
+ output[j] = b1;
+ }
+ j++;
+ if (input[i + 2] != '=')
+ {
+ unsigned char b2 = (unsigned char)((rstr[(int)input[i + 1]] << 4 & 0xf0) +
+ (rstr[(int)input[i + 2]] >> 2 & 0x0f));
+ if (output)
+ {
+ output[j] = b2;
+ }
+ j++;
+ }
+ if (input[i + 3] != '=')
+ {
+ unsigned char b3 = (unsigned char)((rstr[(int)input[i + 2]] << 6 & 0xc0) +
+ rstr[(int)input[i + 3]]);
+ if (output)
+ {
+ output[j] = b3;
+ }
+ j++;
+ }
+ i += 4;
+ }
+ }
+ sz = j;
+}
+
+
+size_t Base64::decode_length(const std::string& str64)
+{
+ if (!str64.size() || str64.size() % 4)
+ return 0;
+ size_t l = 3 * (str64.size() / 4 - 1) + 1;
+ if (str64[str64.size() - 2] != '=')
+ l++;
+ if (str64[str64.size() - 1] != '=')
+ l++;
+ return l;
+}
+
+
+#ifdef SOCKETS_NAMESPACE
+}
+#endif
+
+
diff --git a/Sockets/Base64.h b/Sockets/Base64.h
new file mode 100644
index 0000000..a632bbe
--- /dev/null
+++ b/Sockets/Base64.h
@@ -0,0 +1,77 @@
+/** \file Base64.h
+ ** \date 2004-02-13
+ ** \author grymse@alhem.net
+**/
+/*
+Copyright (C) 2004-2007 Anders Hedstrom
+
+This library is made available under the terms of the GNU GPL.
+
+If you would like to use this library in a closed-source application,
+a separate license agreement is available. For information about
+the closed-source license agreement for the C++ sockets library,
+please visit http://www.alhem.net/Sockets/license.html and/or
+email license@alhem.net.
+
+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.
+*/
+#ifndef _SOCKETS_Base64_H
+#define _SOCKETS_Base64_H
+
+#include "sockets-config.h"
+#ifdef _MSC_VER
+#pragma warning(disable:4514)
+#endif
+
+#include <stdio.h>
+#include <string>
+
+#ifdef SOCKETS_NAMESPACE
+namespace SOCKETS_NAMESPACE {
+#endif
+
+/** \defgroup util Utilities */
+
+/** Base64 encode/decode.
+ \ingroup util */
+class Base64
+{
+public:
+ Base64();
+
+ void encode(FILE *, std::string& , bool add_crlf = true);
+ void encode(const std::string&, std::string& , bool add_crlf = true);
+ void encode(const char *, size_t, std::string& , bool add_crlf = true);
+ void encode(const unsigned char *, size_t, std::string& , bool add_crlf = true);
+
+ void decode(const std::string&, std::string& );
+ void decode(const std::string&, unsigned char *, size_t&);
+
+ size_t decode_length(const std::string& );
+
+private:
+ Base64(const Base64& ) {}
+ Base64& operator=(const Base64& ) { return *this; }
+static const char *bstr;
+static const char rstr[128];
+};
+
+
+#ifdef SOCKETS_NAMESPACE
+}
+#endif
+
+#endif // _SOCKETS_Base64_H
+
diff --git a/Sockets/Debug.cpp b/Sockets/Debug.cpp
new file mode 100644
index 0000000..ce4bad6
--- /dev/null
+++ b/Sockets/Debug.cpp
@@ -0,0 +1,79 @@
+#include "Debug.h"
+#include <stdarg.h>
+
+
+#ifdef SOCKETS_NAMESPACE
+namespace SOCKETS_NAMESPACE {
+#endif
+
+
+std::map<unsigned long, int> Debug::m_level;
+const char *Debug::colors[] = {
+ "\x1B[0;0m", // &n */
+ "\x1B[0;0m\x1B[31m", // &r */
+ "\x1B[0;0m\x1B[32m", // &g */
+ "\x1B[0;0m\x1B[33m", // &y */
+ "\x1B[0;0m\x1B[34m", // &b */
+ "\x1B[0;0m\x1B[35m", // &m */
+ "\x1B[0;0m\x1B[36m", // &c */
+ "\x1B[0;0m\x1B[37m", // &w */
+ "\x1B[0;0m\x1B[30m", // &l */
+ "\x1B[1;31m", // &R */
+ "\x1B[1;32m", // &G */
+ "\x1B[1;33m", // &Y */
+ "\x1B[1;34m", // &B */
+ "\x1B[1;35m", // &M */
+ "\x1B[1;36m", // &C */
+ "\x1B[1;37m", // &W */
+ "\x1B[1;30m" }; // &L */
+
+
+
+void Debug::Print(const char *format, ...)
+{
+ char slask[5000]; // temporary for vsprintf / vsnprintf
+ va_list ap;
+
+ va_start(ap, format);
+#ifdef _WIN32
+ vsprintf(slask, format, ap);
+#else
+ vsnprintf(slask, 5000, format, ap);
+#endif
+ va_end(ap);
+
+ fprintf(stderr, "%s", colors[Utility::ThreadID() % 16 + 1]);
+ for (int i = 0; i < m_level[Utility::ThreadID()]; i++)
+ fprintf(stderr, " ");
+ if (slask[strlen(slask) - 1] == '\n')
+ slask[strlen(slask) - 1] = 0;
+ fprintf(stderr, "%s%s\n", slask, colors[0]);
+}
+
+
+Debug& Debug::operator<<(const std::string& str)
+{
+ m_line += str;
+ return *this;
+}
+
+
+Debug& Debug::operator<<(long l)
+{
+ m_line += Utility::l2string(l);
+ return *this;
+}
+
+
+Debug& Debug::operator<<(endl)
+{
+ Print("%s", m_line.c_str());
+ m_line = "";
+ return *this;
+}
+
+
+#ifdef SOCKETS_NAMESPACE
+} // namespace SOCKETS_NAMESPACE {
+#endif
+
diff --git a/Sockets/Debug.h b/Sockets/Debug.h
new file mode 100644
index 0000000..9bc06b9
--- /dev/null
+++ b/Sockets/Debug.h
@@ -0,0 +1,75 @@
+#ifndef _SOCKETS_Debug_H
+#define _SOCKETS_Debug_H
+
+#include "sockets-config.h"
+#include <string>
+#include "Utility.h"
+#include <map>
+
+
+#ifdef SOCKETS_NAMESPACE
+namespace SOCKETS_NAMESPACE {
+#endif
+
+
+class Debug
+{
+static const char *colors[];
+public:
+ class endl {
+ public:
+ endl() {}
+ virtual ~endl() {}
+ };
+
+public:
+ Debug() {}
+ Debug(const std::string& x) : m_id(0), m_text(x) {
+ fprintf(stderr, "%s", colors[Utility::ThreadID() % 16 + 1]);
+ for (int i = 0; i < m_level[Utility::ThreadID()]; i++)
+ fprintf(stderr, " ");
+ fprintf(stderr, "%s%s\n", x.c_str(), colors[0]);
+ m_level[Utility::ThreadID()]++;
+ }
+ Debug(int id, const std::string& x) : m_id(id), m_text(x) {
+ fprintf(stderr, "%s", colors[Utility::ThreadID() % 16 + 1]);
+ for (int i = 0; i < m_level[Utility::ThreadID()]; i++)
+ fprintf(stderr, " ");
+ fprintf(stderr, "%d> %s%s\n", m_id, x.c_str(), colors[0]);
+ m_level[Utility::ThreadID()]++;
+ }
+ ~Debug() {
+ if (!m_text.empty())
+ {
+ if (m_level[Utility::ThreadID()])
+ m_level[Utility::ThreadID()]--;
+ fprintf(stderr, "%s", colors[Utility::ThreadID() % 16 + 1]);
+ for (int i = 0; i < m_level[Utility::ThreadID()]; i++)
+ fprintf(stderr, " ");
+ if (m_id)
+ fprintf(stderr, "%d> /%s%s\n", m_id, m_text.c_str(), colors[0]);
+ else
+ fprintf(stderr, "/%s%s\n", m_text.c_str(), colors[0]);
+ fflush(stderr);
+ }
+ }
+static void Print(const char *format, ...);
+
+ Debug& operator<<(const std::string& );
+ Debug& operator<<(long);
+ Debug& operator<<(endl);
+
+private:
+ int m_id;
+ std::string m_text;
+static std::map<unsigned long, int> m_level;
+ std::string m_line;
+};
+
+
+#ifdef SOCKETS_NAMESPACE
+} // namespace SOCKETS_NAMESPACE {
+#endif
+
+#endif // _SOCKETS_Debug_H
+
diff --git a/Sockets/DevCpp/Sockets.dev b/Sockets/DevCpp/Sockets.dev
new file mode 100644
index 0000000..fe38522
--- /dev/null
+++ b/Sockets/DevCpp/Sockets.dev
@@ -0,0 +1,1129 @@
+[Project]
+FileName=Sockets.dev
+Name=Sockets
+UnitCount=96
+Type=2
+Ver=1
+ObjFiles=
+Includes=C:\OpenSSL\include
+Libs=C:\OpenSSL\lib\MinGW
+PrivateResource=
+ResourceIncludes=
+MakeIncludes=
+Compiler=
+CppCompiler=-D_VERSION='"2.1.9"'_@@_-D__CYGWIN___@@__@@_
+Linker=../../../../OpenSSL/lib/MinGW/ssleay32.a_@@_../../../../OpenSSL/lib/MinGW/libeay32.a_@@_
+IsCpp=1
+Icon=
+ExeOutput=..\..\lib
+ObjectOutput=
+OverrideOutput=0
+OverrideOutputName=Sockets.a
+HostApplication=
+Folders="Asynchronous DNS","Basic Sockets","File handling","HTTP Sockets",Internal,"Log help classes",SMTP,Threading,"Timer Events",Utilities,"Webserver framework"
+CommandLine=
+UseCustomMakefile=0
+CustomMakefile=
+IncludeVersionInfo=0
+SupportXPThemes=0
+CompilerSet=0
+CompilerSettings=0000000000000000000000
+
+[VersionInfo]
+Major=0
+Minor=1
+Release=1
+Build=1
+LanguageID=1033
+CharsetID=1050
+CompanyName=
+FileVersion=
+FileDescription=Developed using the Dev-C++ IDE
+InternalName=
+LegalCopyright=
+LegalTrademarks=
+OriginalFilename=
+ProductName=
+ProductVersion=
+AutoIncBuildNr=0
+
+[Unit1]
+FileName=..\socket_include.cpp
+CompileCpp=1
+Folder=
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit2]
+FileName=..\socket_include.h
+CompileCpp=1
+Folder=
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit3]
+FileName=..\sockets-config.h
+CompileCpp=1
+Folder=
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit4]
+FileName=..\ResolvServer.cpp
+CompileCpp=1
+Folder=Asynchronous DNS
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit5]
+FileName=..\ResolvServer.h
+CompileCpp=1
+Folder=Asynchronous DNS
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit6]
+FileName=..\ResolvSocket.cpp
+CompileCpp=1
+Folder=Asynchronous DNS
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit7]
+FileName=..\ResolvSocket.h
+CompileCpp=1
+Folder=Asynchronous DNS
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit8]
+FileName=..\ListenSocket.h
+CompileCpp=1
+Folder=Basic Sockets
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit9]
+FileName=..\Socket.cpp
+CompileCpp=1
+Folder=Basic Sockets
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit10]
+FileName=..\Socket.h
+CompileCpp=1
+Folder=Basic Sockets
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit11]
+FileName=..\SocketHandler.cpp
+CompileCpp=1
+Folder=Basic Sockets
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit12]
+FileName=..\SocketHandler.h
+CompileCpp=1
+Folder=Basic Sockets
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit13]
+FileName=..\TcpSocket.cpp
+CompileCpp=1
+Folder=Basic Sockets
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit14]
+FileName=..\TcpSocket.h
+CompileCpp=1
+Folder=Basic Sockets
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit15]
+FileName=..\UdpSocket.cpp
+CompileCpp=1
+Folder=Basic Sockets
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit16]
+FileName=..\UdpSocket.h
+CompileCpp=1
+Folder=Basic Sockets
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit17]
+FileName=..\SctpSocket.h
+CompileCpp=1
+Folder=Basic Sockets
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit18]
+FileName=..\SctpSocket.cpp
+CompileCpp=1
+Folder=Basic Sockets
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit19]
+FileName=..\ISocketHandler.h
+CompileCpp=1
+Folder=Basic Sockets
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit20]
+FileName=..\StreamSocket.h
+CompileCpp=1
+Folder=Basic Sockets
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit21]
+FileName=..\Ipv4Address.h
+CompileCpp=1
+Folder=Basic Sockets
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit22]
+FileName=..\Ipv6Address.cpp
+CompileCpp=1
+Folder=Basic Sockets
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit23]
+FileName=..\Ipv4Address.cpp
+CompileCpp=1
+Folder=Basic Sockets
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit25]
+FileName=..\Ipv6Address.h
+CompileCpp=1
+Folder=Basic Sockets
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit26]
+FileName=..\SocketAddress.h
+CompileCpp=1
+Folder=Basic Sockets
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit27]
+FileName=..\MemFile.h
+CompileCpp=1
+Folder=File handling
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit28]
+FileName=..\File.h
+CompileCpp=1
+Folder=File handling
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit29]
+FileName=..\IFile.h
+CompileCpp=1
+Folder=File handling
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit30]
+FileName=..\MemFile.cpp
+CompileCpp=1
+Folder=File handling
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit31]
+FileName=..\File.cpp
+CompileCpp=1
+Folder=File handling
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit32]
+FileName=..\HttpDebugSocket.cpp
+CompileCpp=1
+Folder=HTTP Sockets
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit33]
+FileName=..\HttpDebugSocket.h
+CompileCpp=1
+Folder=HTTP Sockets
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit34]
+FileName=..\HttpGetSocket.cpp
+CompileCpp=1
+Folder=HTTP Sockets
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit35]
+FileName=..\HttpGetSocket.h
+CompileCpp=1
+Folder=HTTP Sockets
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit36]
+FileName=..\HttpPostSocket.cpp
+CompileCpp=1
+Folder=HTTP Sockets
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit37]
+FileName=..\HttpPostSocket.h
+CompileCpp=1
+Folder=HTTP Sockets
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit38]
+FileName=..\HttpPutSocket.cpp
+CompileCpp=1
+Folder=HTTP Sockets
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit39]
+FileName=..\HttpPutSocket.h
+CompileCpp=1
+Folder=HTTP Sockets
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit40]
+FileName=..\HTTPSocket.cpp
+CompileCpp=1
+Folder=HTTP Sockets
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit41]
+FileName=..\HTTPSocket.h
+CompileCpp=1
+Folder=HTTP Sockets
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit42]
+FileName=..\HttpClientSocket.h
+CompileCpp=1
+Folder=HTTP Sockets
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit43]
+FileName=..\HttpClientSocket.cpp
+CompileCpp=1
+Folder=HTTP Sockets
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit45]
+FileName=..\SSLInitializer.h
+CompileCpp=1
+Folder=Internal
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit46]
+FileName=..\StdLog.h
+CompileCpp=1
+Folder=Log help classes
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit47]
+FileName=..\StdoutLog.cpp
+CompileCpp=1
+Folder=Log help classes
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit48]
+FileName=..\StdoutLog.h
+CompileCpp=1
+Folder=Log help classes
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit49]
+FileName=..\SmtpdSocket.cpp
+CompileCpp=1
+Folder=SMTP
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit50]
+FileName=..\SmtpdSocket.h
+CompileCpp=1
+Folder=SMTP
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit51]
+FileName=..\sockets-config.h
+CompileCpp=1
+Folder=Sockets
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit54]
+FileName=..\Thread.cpp
+CompileCpp=1
+Folder=Threading
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit55]
+FileName=..\Thread.h
+CompileCpp=1
+Folder=Threading
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit56]
+FileName=..\Lock.h
+CompileCpp=1
+Folder=Threading
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit57]
+FileName=..\Lock.cpp
+CompileCpp=1
+Folder=Threading
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit58]
+FileName=..\Mutex.cpp
+CompileCpp=1
+Folder=Threading
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit59]
+FileName=..\Mutex.h
+CompileCpp=1
+Folder=Threading
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit60]
+FileName=..\EventTime.h
+CompileCpp=1
+Folder=Timer Events
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit61]
+FileName=..\Event.h
+CompileCpp=1
+Folder=Timer Events
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit62]
+FileName=..\EventHandler.cpp
+CompileCpp=1
+Folder=Timer Events
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit63]
+FileName=..\IEventOwner.cpp
+CompileCpp=1
+Folder=Timer Events
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit64]
+FileName=..\IEventOwner.h
+CompileCpp=1
+Folder=Timer Events
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit65]
+FileName=..\EventTime.cpp
+CompileCpp=1
+Folder=Timer Events
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit66]
+FileName=..\EventHandler.h
+CompileCpp=1
+Folder=Timer Events
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit67]
+FileName=..\IEventHandler.h
+CompileCpp=1
+Folder=Timer Events
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit68]
+FileName=..\Event.cpp
+CompileCpp=1
+Folder=Timer Events
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit69]
+FileName=..\Base64.cpp
+CompileCpp=1
+Folder=Utilities
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit70]
+FileName=..\Base64.h
+CompileCpp=1
+Folder=Utilities
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit71]
+FileName=..\Parse.cpp
+CompileCpp=1
+Folder=Utilities
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit72]
+FileName=..\Parse.h
+CompileCpp=1
+Folder=Utilities
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit73]
+FileName=..\Utility.cpp
+CompileCpp=1
+Folder=Utilities
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit74]
+FileName=..\Utility.h
+CompileCpp=1
+Folder=Utilities
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit75]
+FileName=..\RandomNumber.h
+CompileCpp=1
+Folder=Utilities
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit76]
+FileName=..\RandomNumber.cpp
+CompileCpp=1
+Folder=Utilities
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit77]
+FileName=..\HttpdSocket.h
+CompileCpp=1
+Folder=Webserver framework
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit78]
+FileName=..\HttpdCookies.h
+CompileCpp=1
+Folder=Webserver framework
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit79]
+FileName=..\HttpdForm.cpp
+CompileCpp=1
+Folder=Webserver framework
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit80]
+FileName=..\HttpdForm.h
+CompileCpp=1
+Folder=Webserver framework
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit81]
+FileName=..\HttpdSocket.cpp
+CompileCpp=1
+Folder=Webserver framework
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit82]
+FileName=..\HttpdCookies.cpp
+CompileCpp=1
+Folder=Webserver framework
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit83]
+FileName=..\Ajp13Socket.cpp
+CompileCpp=1
+Folder=Webserver framework
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit84]
+FileName=..\Ajp13Socket.h
+CompileCpp=1
+Folder=Webserver framework
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit85]
+FileName=..\AjpBaseSocket.cpp
+CompileCpp=1
+Folder=Webserver framework
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit86]
+FileName=..\AjpBaseSocket.h
+CompileCpp=1
+Folder=Webserver framework
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit87]
+FileName=..\HttpBaseSocket.cpp
+CompileCpp=1
+Folder=Webserver framework
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit88]
+FileName=..\HttpBaseSocket.h
+CompileCpp=1
+Folder=Webserver framework
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit89]
+FileName=..\HttpTransaction.cpp
+CompileCpp=1
+Folder=Webserver framework
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit90]
+FileName=..\HttpTransaction.h
+CompileCpp=1
+Folder=Webserver framework
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit91]
+FileName=..\HttpRequest.cpp
+CompileCpp=1
+Folder=Webserver framework
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit92]
+FileName=..\HttpRequest.h
+CompileCpp=1
+Folder=Webserver framework
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit93]
+FileName=..\HttpResponse.cpp
+CompileCpp=1
+Folder=Webserver framework
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit94]
+FileName=..\HttpResponse.h
+CompileCpp=1
+Folder=Webserver framework
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit95]
+FileName=..\ajp13.h
+CompileCpp=1
+Folder=Webserver framework
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit96]
+FileName=..\IHttpServer.h
+CompileCpp=1
+Folder=Webserver framework
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit97]
+FileName=..\HttpTransaction.cpp
+CompileCpp=1
+Folder=Webserver framework
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit98]
+FileName=..\HttpTransaction.h
+CompileCpp=1
+Folder=Webserver framework
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit99]
+FileName=..\HttpRequest.cpp
+CompileCpp=1
+Folder=Webserver framework
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit100]
+FileName=..\HttpRequest.h
+CompileCpp=1
+Folder=Webserver framework
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit101]
+FileName=..\HttpResponse.cpp
+CompileCpp=1
+Folder=Webserver framework
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit102]
+FileName=..\HttpResponse.h
+CompileCpp=1
+Folder=Webserver framework
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit103]
+FileName=..\ajp13.h
+CompileCpp=1
+Folder=Webserver framework
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit104]
+FileName=..\IHttpServer.h
+CompileCpp=1
+Folder=Webserver framework
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit105]
+FileName=..\HttpResponse.cpp
+CompileCpp=1
+Folder=Webserver framework
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit106]
+FileName=..\HttpResponse.h
+CompileCpp=1
+Folder=Webserver framework
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit107]
+FileName=..\ajp13.h
+CompileCpp=1
+Folder=Webserver framework
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit108]
+FileName=..\IHttpServer.h
+CompileCpp=1
+Folder=Webserver framework
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit24]
+FileName=..\StreamSocket.cpp
+CompileCpp=1
+Folder=Basic Sockets
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit44]
+FileName=..\SSLInitializer.cpp
+CompileCpp=1
+Folder=Internal
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit52]
+FileName=..\Exception.h
+CompileCpp=1
+Folder=Sockets
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit53]
+FileName=..\Exception.cpp
+CompileCpp=1
+Folder=Sockets
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
diff --git a/Sockets/DevCpp/Test.dev b/Sockets/DevCpp/Test.dev
new file mode 100644
index 0000000..913d938
--- /dev/null
+++ b/Sockets/DevCpp/Test.dev
@@ -0,0 +1,59 @@
+[Project]
+FileName=Test.dev
+Name=Test
+UnitCount=1
+Type=1
+Ver=1
+ObjFiles=
+Includes=..;C:\OpenSSL\include
+Libs=C:\OpenSSL\lib\MinGW
+PrivateResource=
+ResourceIncludes=
+MakeIncludes=
+Compiler=
+CppCompiler=-DHAVE_OPENSSL_@@_-D__CYGWIN___@@_
+Linker=../../lib/Sockets.a_@@_../../../../OpenSSL/lib/MinGW/ssleay32.a_@@_../../../../OpenSSL/lib/MinGW/libeay32.a_@@_../../../../Dev-Cpp/lib/libwsock32.a_@@_../../../../Dev-Cpp/lib/libws2_32.a_@@_
+IsCpp=1
+Icon=
+ExeOutput=..\..\bin
+ObjectOutput=bin
+OverrideOutput=0
+OverrideOutputName=Test.exe
+HostApplication=
+Folders=
+CommandLine=
+UseCustomMakefile=0
+CustomMakefile=
+IncludeVersionInfo=0
+SupportXPThemes=0
+CompilerSet=0
+CompilerSettings=0000000000000000000000
+
+[VersionInfo]
+Major=0
+Minor=1
+Release=1
+Build=1
+LanguageID=1033
+CharsetID=1252
+CompanyName=
+FileVersion=
+FileDescription=Developed using the Dev-C++ IDE
+InternalName=
+LegalCopyright=
+LegalTrademarks=
+OriginalFilename=
+ProductName=
+ProductVersion=
+AutoIncBuildNr=0
+
+[Unit1]
+FileName=..\tests\sockets_test.cpp
+CompileCpp=1
+Folder=Test
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
diff --git a/Sockets/Event.cpp b/Sockets/Event.cpp
new file mode 100644
index 0000000..d8d1bba
--- /dev/null
+++ b/Sockets/Event.cpp
@@ -0,0 +1,85 @@
+/** \file Event.cpp
+ ** \date 2005-12-07
+ ** \author grymse@alhem.net
+**/
+/*
+Copyright (C) 2005,2007 Anders Hedstrom
+
+This library is made available under the terms of the GNU GPL.
+
+If you would like to use this library in a closed-source application,
+a separate license agreement is available. For information about
+the closed-source license agreement for the C++ sockets library,
+please visit http://www.alhem.net/Sockets/license.html and/or
+email license@alhem.net.
+
+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.
+*/
+#include "Event.h"
+#ifdef _WIN32
+#else
+#include <sys/time.h>
+#endif
+
+//#include "IEventOwner.h"
+
+
+#ifdef SOCKETS_NAMESPACE
+namespace SOCKETS_NAMESPACE {
+#endif
+
+
+// statics
+long Event::m_unique_id = 0;
+
+
+Event::Event(IEventOwner *from,long sec,long usec) : m_from(from), m_time(sec, usec), m_id(++m_unique_id)
+{
+}
+
+
+Event::~Event()
+{
+}
+
+
+bool Event::operator<(Event& e)
+{
+ return m_time < e.m_time;
+}
+
+
+long Event::GetID()
+{
+ return m_id;
+}
+
+
+const EventTime& Event::GetTime() const
+{
+ return m_time;
+}
+
+
+IEventOwner *Event::GetFrom()
+{
+ return m_from;
+}
+
+
+#ifdef SOCKETS_NAMESPACE
+}
+#endif
+
diff --git a/Sockets/Event.h b/Sockets/Event.h
new file mode 100644
index 0000000..cf6521b
--- /dev/null
+++ b/Sockets/Event.h
@@ -0,0 +1,76 @@
+/** \file Event.h
+ ** \date 2005-12-07
+ ** \author grymse@alhem.net
+**/
+/*
+Copyright (C) 2005,2007 Anders Hedstrom
+
+This library is made available under the terms of the GNU GPL.
+
+If you would like to use this library in a closed-source application,
+a separate license agreement is available. For information about
+the closed-source license agreement for the C++ sockets library,
+please visit http://www.alhem.net/Sockets/license.html and/or
+email license@alhem.net.
+
+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.
+*/
+#ifndef _SOCKETS_Event_H
+#define _SOCKETS_Event_H
+
+#include "sockets-config.h"
+#ifdef _WIN32
+#else
+#include <sys/select.h>
+#endif
+#include "EventTime.h"
+
+#ifdef SOCKETS_NAMESPACE
+namespace SOCKETS_NAMESPACE {
+#endif
+
+
+class IEventOwner;
+
+/** Store information about a timer event.
+ \ingroup timer */
+class Event
+{
+public:
+ Event(IEventOwner *,long sec,long usec);
+ ~Event();
+
+ bool operator<(Event&);
+ long GetID();
+ const EventTime& GetTime() const;
+ IEventOwner *GetFrom();
+
+private:
+ Event(const Event& ) {} // copy constructor
+ Event& operator=(const Event& ) { return *this; } // assignment operator
+ IEventOwner *m_from;
+ EventTime m_time;
+ static long m_unique_id;
+ long m_id;
+};
+
+
+
+#ifdef SOCKETS_NAMESPACE
+}
+#endif
+
+#endif // _SOCKETS_Event_H
+
diff --git a/Sockets/EventHandler.cpp b/Sockets/EventHandler.cpp
new file mode 100644
index 0000000..4d90342
--- /dev/null
+++ b/Sockets/EventHandler.cpp
@@ -0,0 +1,223 @@
+/** \file EventHandler.cpp
+ ** \date 2005-12-07
+ ** \author grymse@alhem.net
+**/
+/*
+Copyright (C) 2005,2007 Anders Hedstrom
+
+This library is made available under the terms of the GNU GPL.
+
+If you would like to use this library in a closed-source application,
+a separate license agreement is available. For information about
+the closed-source license agreement for the C++ sockets library,
+please visit http://www.alhem.net/Sockets/license.html and/or
+email license@alhem.net.
+
+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 _MSC_VER
+#pragma warning(disable:4786)
+#endif
+#include "EventHandler.h"
+#include "IEventOwner.h"
+#include "Event.h"
+#include "Socket.h"
+#include "TcpSocket.h"
+#include "ListenSocket.h"
+
+
+#ifdef SOCKETS_NAMESPACE
+namespace SOCKETS_NAMESPACE {
+#endif
+
+
+EventHandler::EventHandler(StdLog *p) : SocketHandler(p), m_quit(false), m_socket(NULL)
+{
+}
+
+
+EventHandler::EventHandler(Mutex& m,StdLog *p) : SocketHandler(m, p), m_quit(false), m_socket(NULL)
+{
+}
+
+
+EventHandler::~EventHandler()
+{
+ while (m_events.size())
+ {
+ std::list<Event *>::iterator it = m_events.begin();
+ Event *e = *it;
+ e -> GetFrom() -> SetHandlerInvalid();
+ delete e;
+ m_events.erase(it);
+ }
+}
+
+
+bool EventHandler::GetTimeUntilNextEvent(struct timeval *tv)
+{
+ if (!m_events.size())
+ return false;
+ std::list<Event *>::iterator it = m_events.begin();
+ if (it != m_events.end())
+ {
+ EventTime now;
+ mytime_t diff = (*it) -> GetTime() - now;
+ if (diff < 1)
+ {
+ diff = 1;
+ }
+ tv -> tv_sec = static_cast<long>(diff / 1000000);
+ tv -> tv_usec = static_cast<long>(diff % 1000000);
+ return true;
+ }
+ return false;
+}
+
+
+void EventHandler::CheckEvents()
+{
+ EventTime now;
+ std::list<Event *>::iterator it = m_events.begin();
+ while (it != m_events.end() && (*it) -> GetTime() < now)
+ {
+ Event *e = *it;
+ Socket *s = dynamic_cast<Socket *>(e -> GetFrom());
+ /*
+ s == NULL This is another object implementing 'IEventOwner' and not a socket.
+ s != NULL This is a Socket implementing IEventOwner, and we can check that the
+ object instance still is valid using SocketHandler::Valid.
+ */
+ if (!s || (s && Valid(s)))
+ {
+ e -> GetFrom() -> OnEvent(e -> GetID());
+ }
+ for (it = m_events.begin(); it != m_events.end(); ++it)
+ if (*it == e)
+ break;
+ delete e;
+ if (it != m_events.end())
+ m_events.erase(it);
+ it = m_events.begin();
+ }
+}
+
+
+long EventHandler::AddEvent(IEventOwner *from,long sec,long usec)
+{
+ Event *e = new Event(from, sec, usec);
+ std::list<Event *>::iterator it = m_events.begin();
+ while (it != m_events.end() && *(*it) < *e)
+ {
+ it++;
+ }
+ m_events.insert(it, e);
+ if (m_socket)
+ {
+ m_socket -> Send("\n");
+ }
+ return e -> GetID();
+}
+
+
+void EventHandler::ClearEvents(IEventOwner *from)
+{
+ bool repeat;
+ do
+ {
+ repeat = false;
+ for (std::list<Event *>::iterator it = m_events.begin(); it != m_events.end(); it++)
+ {
+ Event *e = *it;
+ if (e -> GetFrom() == from)
+ {
+ delete e;
+ m_events.erase(it);
+ repeat = true;
+ break;
+ }
+ }
+ } while (repeat);
+}
+
+
+void EventHandler::EventLoop()
+{
+ while (!m_quit)
+ {
+ struct timeval tv;
+ if (GetTimeUntilNextEvent(&tv))
+ {
+ Select(&tv);
+ CheckEvents();
+ }
+ else
+ {
+ Select();
+ }
+ }
+}
+
+
+void EventHandler::SetQuit(bool x)
+{
+ m_quit = x;
+}
+
+
+void EventHandler::RemoveEvent(IEventOwner *from, long eid)
+{
+ for (std::list<Event *>::iterator it = m_events.begin(); it != m_events.end(); it++)
+ {
+ Event *e = *it;
+ if (from == e -> GetFrom() && eid == e -> GetID())
+ {
+ delete e;
+ m_events.erase(it);
+ break;
+ }
+ }
+}
+
+
+void EventHandler::Add(Socket *p)
+{
+ if (!m_socket)
+ {
+ ListenSocket<TcpSocket> *l = new ListenSocket<TcpSocket>(*this);
+ l -> SetDeleteByHandler();
+ l -> Bind("127.0.0.1", 0);
+ m_port = l -> GetPort();
+ SocketHandler::Add(l);
+ m_socket = new TcpSocket( *this );
+ m_socket -> SetDeleteByHandler();
+ m_socket -> SetConnectTimeout(5);
+ m_socket -> SetConnectionRetry(-1);
+#ifdef ENABLE_RECONNECT
+ m_socket -> SetReconnect(true);
+#endif
+ m_socket -> Open("127.0.0.1", m_port);
+ SocketHandler::Add(m_socket);
+ }
+ SocketHandler::Add( p );
+}
+
+
+#ifdef SOCKETS_NAMESPACE
+}
+#endif
+
+
+
diff --git a/Sockets/EventHandler.h b/Sockets/EventHandler.h
new file mode 100644
index 0000000..9ca7cde
--- /dev/null
+++ b/Sockets/EventHandler.h
@@ -0,0 +1,85 @@
+/** \file EventHandler.h
+ ** \date 2005-12-07
+ ** \author grymse@alhem.net
+**/
+/*
+Copyright (C) 2005,2007 Anders Hedstrom
+
+This library is made available under the terms of the GNU GPL.
+
+If you would like to use this library in a closed-source application,
+a separate license agreement is available. For information about
+the closed-source license agreement for the C++ sockets library,
+please visit http://www.alhem.net/Sockets/license.html and/or
+email license@alhem.net.
+
+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.
+*/
+#ifndef _SOCKETS_EventHandler_H
+#define _SOCKETS_EventHandler_H
+
+#include "sockets-config.h"
+#include "SocketHandler.h"
+#include "IEventHandler.h"
+
+#ifdef SOCKETS_NAMESPACE
+namespace SOCKETS_NAMESPACE {
+#endif
+
+
+class StdLog;
+class IEventOwner;
+class Event;
+class TcpSocket;
+
+/** SocketHandler implementing the IEventHandler interface.
+ \ingroup timer */
+class EventHandler : public SocketHandler,public IEventHandler
+{
+public:
+ EventHandler(StdLog * = NULL);
+ EventHandler(Mutex&,StdLog * = NULL);
+ ~EventHandler();
+
+ bool GetTimeUntilNextEvent(struct timeval *tv);
+ void CheckEvents();
+ long AddEvent(IEventOwner *from,long sec,long usec);
+ void ClearEvents(IEventOwner *from);
+ void RemoveEvent(IEventOwner *from,long eid);
+
+ /** SocketHandler while() loop implemented with event functionality. */
+ void EventLoop();
+ /** Stop event loop. */
+ void SetQuit(bool = true);
+
+ void Add(Socket *);
+
+private:
+ EventHandler(const EventHandler& ) {} // copy constructor
+ EventHandler& operator=(const EventHandler& ) { return *this; } // assignment operator
+ std::list<Event *> m_events;
+ bool m_quit;
+ TcpSocket *m_socket;
+ port_t m_port;
+};
+
+
+
+#ifdef SOCKETS_NAMESPACE
+}
+#endif
+
+#endif // _SOCKETS_EventHandler_H
+
diff --git a/Sockets/EventTime.cpp b/Sockets/EventTime.cpp
new file mode 100644
index 0000000..a58cbb3
--- /dev/null
+++ b/Sockets/EventTime.cpp
@@ -0,0 +1,105 @@
+/** \file EventTime.cpp
+ ** \date 2005-12-07
+ ** \author grymse@alhem.net
+**/
+/*
+Copyright (C) 2005,2007 Anders Hedstrom
+
+This library is made available under the terms of the GNU GPL.
+
+If you would like to use this library in a closed-source application,
+a separate license agreement is available. For information about
+the closed-source license agreement for the C++ sockets library,
+please visit http://www.alhem.net/Sockets/license.html and/or
+email license@alhem.net.
+
+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 MACOSX
+#include <stdint.h>
+#include <sys/types.h>
+#include <signal.h>
+#endif
+#include "EventTime.h"
+#ifdef _WIN32
+#include <windows.h>
+#else
+#include <sys/select.h>
+#include <sys/time.h>
+#endif
+
+
+
+#ifdef SOCKETS_NAMESPACE
+namespace SOCKETS_NAMESPACE {
+#endif
+
+
+EventTime::EventTime() : m_time(Tick())
+{
+}
+
+
+EventTime::EventTime(mytime_t sec,long usec) : m_time(Tick())
+{
+ m_time += sec * 1000000 + usec;
+}
+
+
+EventTime::~EventTime()
+{
+}
+
+
+mytime_t EventTime::Tick()
+{
+ mytime_t t;
+#ifdef _WIN32
+ FILETIME ft;
+ GetSystemTimeAsFileTime(&ft);
+ t = ft.dwHighDateTime;
+ t = t << 32;
+ t += ft.dwLowDateTime;
+ t /= 10; // us
+#else
+ struct timeval tv;
+ struct timezone tz;
+ gettimeofday(&tv, &tz);
+ t = tv.tv_sec;
+ t *= 1000000;
+ t += tv.tv_usec;
+#endif
+ return t;
+}
+
+
+EventTime EventTime::operator - (const EventTime& x) const
+{
+ EventTime t;
+ t.m_time = m_time - x.m_time;
+ return t;
+}
+
+
+bool EventTime::operator < (const EventTime& x) const
+{
+ return m_time < x.m_time;
+}
+
+
+#ifdef SOCKETS_NAMESPACE
+}
+#endif
+
diff --git a/Sockets/EventTime.h b/Sockets/EventTime.h
new file mode 100644
index 0000000..5c77695
--- /dev/null
+++ b/Sockets/EventTime.h
@@ -0,0 +1,77 @@
+/** \file EventTime.h
+ ** \date 2005-12-07
+ ** \author grymse@alhem.net
+**/
+/*
+Copyright (C) 2005,2007 Anders Hedstrom
+
+This library is made available under the terms of the GNU GPL.
+
+If you would like to use this library in a closed-source application,
+a separate license agreement is available. For information about
+the closed-source license agreement for the C++ sockets library,
+please visit http://www.alhem.net/Sockets/license.html and/or
+email license@alhem.net.
+
+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.
+*/
+#ifndef _SOCKETS_EventTime_H
+#define _SOCKETS_EventTime_H
+
+#include "sockets-config.h"
+#ifdef SOCKETS_NAMESPACE
+namespace SOCKETS_NAMESPACE {
+#endif
+
+
+#if defined( _WIN32) && !defined(__CYGWIN__)
+typedef __int64 mytime_t;
+#else
+#include <inttypes.h> // int64_t
+typedef int64_t mytime_t;
+#endif
+
+
+/** \defgroup timer EventTimer event handling */
+
+/** EventTime primitive, returns current time as a 64-bit number.
+ \ingroup timer */
+class EventTime
+{
+public:
+ EventTime();
+ EventTime(mytime_t sec,long usec);
+ ~EventTime();
+
+ static mytime_t Tick();
+
+ operator mytime_t () { return m_time; }
+ EventTime operator - (const EventTime& x) const;
+ bool operator < (const EventTime& x) const;
+
+private:
+ EventTime(const EventTime& ) {} // copy constructor
+ EventTime& operator=(const EventTime& ) { return *this; } // assignment operator
+ mytime_t m_time;
+};
+
+
+
+#ifdef SOCKETS_NAMESPACE
+}
+#endif
+
+#endif // _SOCKETS_EventTime_H
+
diff --git a/Sockets/Exception.cpp b/Sockets/Exception.cpp
new file mode 100644
index 0000000..a005669
--- /dev/null
+++ b/Sockets/Exception.cpp
@@ -0,0 +1,48 @@
+/**
+ ** \file Exception.cpp
+ ** \date 2007-09-28
+ ** \author grymse@alhem.net
+**/
+/*
+Copyright (C) 2007 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 _MSC_VER
+#pragma warning(disable:4786)
+#endif
+#include "Exception.h"
+
+#ifdef SOCKETS_NAMESPACE
+namespace SOCKETS_NAMESPACE {
+#endif
+
+
+
+Exception::Exception(const std::string& description) : m_description(description)
+{
+}
+
+
+const std::string Exception::ToString() const
+{
+ return m_description;
+}
+
+
+#ifdef SOCKETS_NAMESPACE
+} // namespace SOCKETS_NAMESPACE {
+#endif
+
diff --git a/Sockets/Exception.h b/Sockets/Exception.h
new file mode 100644
index 0000000..81ba737
--- /dev/null
+++ b/Sockets/Exception.h
@@ -0,0 +1,58 @@
+/**
+ ** \file Exception.h
+ ** \date 2007-09-28
+ ** \author grymse@alhem.net
+**/
+/*
+Copyright (C) 2007 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.
+*/
+#ifndef _Sockets_Exception_H
+#define _Sockets_Exception_H
+
+#include <string>
+
+#ifdef SOCKETS_NAMESPACE
+namespace SOCKETS_NAMESPACE {
+#endif
+
+
+
+class Exception
+{
+public:
+ Exception(const std::string& description);
+ virtual ~Exception() {}
+
+ virtual const std::string ToString() const;
+
+ Exception(const Exception& ) {} // copy constructor
+
+ Exception& operator=(const Exception& ) { return *this; } // assignment operator
+
+private:
+ std::string m_description;
+
+};
+
+
+
+#ifdef SOCKETS_NAMESPACE
+} // namespace SOCKETS_NAMESPACE {
+#endif
+
+#endif // _Sockets_Exception_H
+
diff --git a/Sockets/File.cpp b/Sockets/File.cpp
new file mode 100644
index 0000000..4c1e5bf
--- /dev/null
+++ b/Sockets/File.cpp
@@ -0,0 +1,169 @@
+/** \file File.cpp
+ ** \date 2005-04-25
+ ** \author grymse@alhem.net
+**/
+/*
+Copyright (C) 2004-2007 Anders Hedstrom
+
+This library is made available under the terms of the GNU GPL.
+
+If you would like to use this library in a closed-source application,
+a separate license agreement is available. For information about
+the closed-source license agreement for the C++ sockets library,
+please visit http://www.alhem.net/Sockets/license.html and/or
+email license@alhem.net.
+
+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.
+*/
+#include <stdarg.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#ifndef _WIN32
+#include <unistd.h>
+#endif
+
+#include "File.h"
+
+#ifdef SOCKETS_NAMESPACE
+namespace SOCKETS_NAMESPACE {
+#endif
+
+
+File::File()
+:m_fil(NULL)
+,m_rptr(0)
+,m_wptr(0)
+{
+}
+
+
+File::~File()
+{
+ fclose();
+}
+
+
+bool File::fopen(const std::string& path, const std::string& mode)
+{
+ m_path = path;
+ m_mode = mode;
+ m_fil = ::fopen(path.c_str(), mode.c_str());
+ return m_fil ? true : false;
+}
+
+
+void File::fclose()
+{
+ if (m_fil)
+ {
+ ::fclose(m_fil);
+ m_fil = NULL;
+ }
+}
+
+
+
+size_t File::fread(char *ptr, size_t size, size_t nmemb) const
+{
+ size_t r = 0;
+ if (m_fil)
+ {
+ fseek(m_fil, m_rptr, SEEK_SET);
+ r = ::fread(ptr, size, nmemb, m_fil);
+ m_rptr = ftell(m_fil);
+ }
+ return r;
+}
+
+
+size_t File::fwrite(const char *ptr, size_t size, size_t nmemb)
+{
+ size_t r = 0;
+ if (m_fil)
+ {
+ fseek(m_fil, m_wptr, SEEK_SET);
+ r = ::fwrite(ptr, size, nmemb, m_fil);
+ m_wptr = ftell(m_fil);
+ }
+ return r;
+}
+
+
+
+char *File::fgets(char *s, int size) const
+{
+ char *r = NULL;
+ if (m_fil)
+ {
+ fseek(m_fil, m_rptr, SEEK_SET);
+ r = ::fgets(s, size, m_fil);
+ m_rptr = ftell(m_fil);
+ }
+ return r;
+}
+
+
+void File::fprintf(const char *format, ...)
+{
+ if (!m_fil)
+ return;
+ va_list ap;
+ va_start(ap, format);
+ fseek(m_fil, m_rptr, SEEK_SET);
+ vfprintf(m_fil, format, ap);
+ m_rptr = ftell(m_fil);
+ va_end(ap);
+}
+
+
+off_t File::size() const
+{
+ struct stat st;
+ if (stat(m_path.c_str(), &st) == -1)
+ {
+ return 0;
+ }
+ return st.st_size;
+}
+
+
+bool File::eof() const
+{
+ if (m_fil)
+ {
+ if (feof(m_fil))
+ return true;
+ }
+ return false;
+}
+
+
+void File::reset_read() const
+{
+ m_rptr = 0;
+}
+
+
+void File::reset_write()
+{
+ m_wptr = 0;
+}
+
+
+#ifdef SOCKETS_NAMESPACE
+}
+#endif
+
+
diff --git a/Sockets/File.h b/Sockets/File.h
new file mode 100644
index 0000000..58a1b71
--- /dev/null
+++ b/Sockets/File.h
@@ -0,0 +1,84 @@
+/** \file File.h
+ ** \date 2005-04-25
+ ** \author grymse@alhem.net
+**/
+/*
+Copyright (C) 2004-2007 Anders Hedstrom
+
+This library is made available under the terms of the GNU GPL.
+
+If you would like to use this library in a closed-source application,
+a separate license agreement is available. For information about
+the closed-source license agreement for the C++ sockets library,
+please visit http://www.alhem.net/Sockets/license.html and/or
+email license@alhem.net.
+
+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.
+*/
+#ifndef _SOCKETS_File_H
+#define _SOCKETS_File_H
+
+#include "sockets-config.h"
+#include "IFile.h"
+#include <stdio.h>
+
+#ifdef SOCKETS_NAMESPACE
+namespace SOCKETS_NAMESPACE {
+#endif
+
+
+/** IFile implementation of a disk file.
+ \ingroup file */
+class File : public IFile
+{
+public:
+ File();
+ ~File();
+
+ bool fopen(const std::string&, const std::string&);
+ void fclose();
+
+ size_t fread(char *, size_t, size_t) const;
+ size_t fwrite(const char *, size_t, size_t);
+
+ char *fgets(char *, int) const;
+ void fprintf(const char *format, ...);
+
+ off_t size() const;
+ bool eof() const;
+
+ void reset_read() const;
+ void reset_write();
+
+private:
+ File(const File& ) {} // copy constructor
+ File& operator=(const File& ) { return *this; } // assignment operator
+
+ std::string m_path;
+ std::string m_mode;
+ FILE *m_fil;
+ mutable long m_rptr;
+ long m_wptr;
+};
+
+
+
+
+#ifdef SOCKETS_NAMESPACE
+}
+#endif
+
+#endif // _SOCKETS_File_H
+
diff --git a/Sockets/HTTPSocket.cpp b/Sockets/HTTPSocket.cpp
new file mode 100644
index 0000000..ca49822
--- /dev/null
+++ b/Sockets/HTTPSocket.cpp
@@ -0,0 +1,413 @@
+/** \file HTTPSocket.cpp
+ ** \date 2004-04-06
+ ** \author grymse@alhem.net
+**/
+/*
+Copyright (C) 2004-2007 Anders Hedstrom
+
+This library is made available under the terms of the GNU GPL.
+
+If you would like to use this library in a closed-source application,
+a separate license agreement is available. For information about
+the closed-source license agreement for the C++ sockets library,
+please visit http://www.alhem.net/Sockets/license.html and/or
+email license@alhem.net.
+
+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 _MSC_VER
+#pragma warning(disable:4786)
+#endif
+#include "HTTPSocket.h"
+#include "Parse.h"
+#include "ISocketHandler.h"
+#include "Utility.h"
+#include <stdarg.h>
+
+#ifdef SOCKETS_NAMESPACE
+namespace SOCKETS_NAMESPACE {
+#endif
+
+
+HTTPSocket::HTTPSocket(ISocketHandler& h)
+:TcpSocket(h)
+,m_first(true)
+,m_header(true)
+,m_http_version("HTTP/1.0")
+,m_request(false)
+,m_response(false)
+,m_body_size_left(0)
+,m_b_http_1_1(false)
+,m_b_keepalive(false)
+{
+ SetLineProtocol();
+ DisableInputBuffer();
+}
+
+
+HTTPSocket::~HTTPSocket()
+{
+}
+
+
+void HTTPSocket::OnRawData(const char *buf,size_t len)
+{
+ if (!m_header)
+ {
+ if (!m_b_http_1_1 || !m_b_keepalive)
+ {
+ OnData(buf, len);
+ }
+ else
+ {
+ size_t sz = m_body_size_left < len ? m_body_size_left : len;
+ OnData(buf, sz);
+ m_body_size_left -= sz;
+ if (!m_body_size_left)
+ {
+ SetLineProtocol( true );
+ m_first = true;
+ m_header = true;
+ m_body_size_left = 0;
+ if (len - sz > 0)
+ {
+ char tmp[TCP_BUFSIZE_READ];
+ memcpy(tmp, buf + sz, len - sz);
+ tmp[len - sz] = 0;
+ OnRead( tmp, len - sz );
+ }
+ }
+ }
+ }
+}
+
+
+void HTTPSocket::OnLine(const std::string& line)
+{
+ if (m_first)
+ {
+ Parse pa(line);
+ std::string str = pa.getword();
+ if (str.size() > 4 && Utility::ToLower(str.substr(0,5)) == "http/") // response
+ {
+ m_http_version = str;
+ m_status = pa.getword();
+ m_status_text = pa.getrest();
+ m_response = true;
+ }
+ else // request
+ {
+ m_method = str;
+ m_url = pa.getword();
+ size_t spl = m_url.find("?");
+ if (spl != std::string::npos)
+ {
+ m_uri = m_url.substr(0,spl);
+ m_query_string = m_url.substr(spl + 1);
+ }
+ else
+ {
+ m_uri = m_url;
+ m_query_string = "";
+ }
+ m_http_version = pa.getword();
+ m_b_http_1_1 = m_http_version.size() > 4 && m_http_version.substr(4) == "/1.1";
+ m_b_keepalive = m_b_http_1_1;
+ m_request = true;
+ }
+ m_first = false;
+ OnFirst();
+ return;
+ }
+ if (!line.size())
+ {
+ if (m_body_size_left || !m_b_http_1_1 || !m_b_keepalive)
+ {
+ SetLineProtocol(false);
+ m_header = false;
+ }
+ OnHeaderComplete();
+ return;
+ }
+ Parse pa(line,":");
+ std::string key = pa.getword();
+ std::string value = pa.getrest();
+ OnHeader(key,value);
+ if (Utility::ToLower(key) == "content-length")
+ {
+ m_body_size_left = atol(value.c_str());
+ }
+ if (m_b_http_1_1 && Utility::ToLower(key) == "connection")
+ {
+ m_b_keepalive = Utility::ToLower(value) != "close";
+ }
+ /* If remote end tells us to keep connection alive, and we're operating
+ in http/1.1 mode (not http/1.0 mode), then we mark the socket to be
+ retained. */
+#ifdef ENABLE_POOL
+ if (m_b_http_1_1 && m_b_keepalive)
+ {
+ SetRetain();
+ }
+#endif
+}
+
+
+void HTTPSocket::SendResponse()
+{
+ std::string msg;
+ msg = m_http_version + " " + m_status + " " + m_status_text + "\r\n";
+ for (string_m::iterator it = m_response_header.begin(); it != m_response_header.end(); it++)
+ {
+ std::string key = (*it).first;
+ std::string val = (*it).second;
+ msg += key + ": " + val + "\r\n";
+ }
+ for (std::list<std::pair<std::string, std::string> >::iterator it2 = m_response_header_append.begin(); it2 != m_response_header_append.end(); ++it2)
+ {
+ msg += it2 -> first + ": " + it2 -> second + "\r\n";
+ }
+ msg += "\r\n";
+ Send( msg );
+}
+
+
+void HTTPSocket::AddResponseHeader(const std::string& header, const char *format, ...)
+{
+ char slask[5000]; // temporary for vsprintf / vsnprintf
+ va_list ap;
+
+ va_start(ap, format);
+#ifdef _WIN32
+ vsprintf(slask, format, ap);
+#else
+ vsnprintf(slask, 5000, format, ap);
+#endif
+ va_end(ap);
+
+ m_response_header[header] = slask;
+}
+
+
+void HTTPSocket::SendRequest()
+{
+ std::string msg;
+ msg = m_method + " " + m_url + " " + m_http_version + "\r\n";
+ for (string_m::iterator it = m_response_header.begin(); it != m_response_header.end(); it++)
+ {
+ std::string key = (*it).first;
+ std::string val = (*it).second;
+ msg += key + ": " + val + "\r\n";
+ }
+ msg += "\r\n";
+ Send( msg );
+}
+
+
+std::string HTTPSocket::MyUseragent()
+{
+ std::string version = "C++Sockets/";
+#ifdef _VERSION
+ version += _VERSION;
+#endif
+ return version;
+}
+
+
+void HTTPSocket::Reset()
+{
+ m_first = true;
+ m_header = true;
+ m_request = false;
+ m_response = false;
+ SetLineProtocol(true);
+ while (m_response_header.size())
+ {
+ string_m::iterator it = m_response_header.begin();
+ m_response_header.erase(it);
+ }
+ while (m_response_header_append.size())
+ {
+ std::list<std::pair<std::string, std::string> >::iterator it = m_response_header_append.begin();
+ m_response_header_append.erase(it);
+ }
+
+}
+
+
+const std::string& HTTPSocket::GetMethod()
+{
+ return m_method;
+}
+
+
+void HTTPSocket::SetMethod(const std::string& x)
+{
+ m_method = x;
+}
+
+
+const std::string& HTTPSocket::GetUrl()
+{
+ return m_url;
+}
+
+
+void HTTPSocket::SetUrl(const std::string& x)
+{
+ m_url = x;
+}
+
+
+const std::string& HTTPSocket::GetUri()
+{
+ return m_uri;
+}
+
+
+const std::string& HTTPSocket::GetQueryString()
+{
+ return m_query_string;
+}
+
+
+const std::string& HTTPSocket::GetHttpVersion()
+{
+ return m_http_version;
+}
+
+
+const std::string& HTTPSocket::GetStatus()
+{
+ return m_status;
+}
+
+
+const std::string& HTTPSocket::GetStatusText()
+{
+ return m_status_text;
+}
+
+
+bool HTTPSocket::IsRequest()
+{
+ return m_request;
+}
+
+
+bool HTTPSocket::IsResponse()
+{
+ return m_response;
+}
+
+
+void HTTPSocket::SetHttpVersion(const std::string& x)
+{
+ m_http_version = x;
+}
+
+
+void HTTPSocket::SetStatus(const std::string& x)
+{
+ m_status = x;
+}
+
+
+void HTTPSocket::SetStatusText(const std::string& x)
+{
+ m_status_text = x;
+}
+
+
+void HTTPSocket::AddResponseHeader(const std::string& x,const std::string& y)
+{
+ m_response_header[Utility::ToLower(x)] = y;
+}
+
+
+void HTTPSocket::AppendResponseHeader(const std::string& x,const std::string& y)
+{
+ m_response_header_append.push_back(std::pair<std::string, std::string>(Utility::ToLower(x),y));
+}
+
+
+void HTTPSocket::SetUri(const std::string& x)
+{
+ m_uri = x;
+}
+
+
+void HTTPSocket::url_this(const std::string& url_in,std::string& protocol,std::string& host,port_t& port,std::string& url,std::string& file)
+{
+ Parse pa(url_in,"/");
+ protocol = pa.getword(); // http
+ if (!strcasecmp(protocol.c_str(), "https:"))
+ {
+#ifdef HAVE_OPENSSL
+ EnableSSL();
+#else
+ Handler().LogError(this, "url_this", -1, "SSL not available", LOG_LEVEL_WARNING);
+#endif
+ port = 443;
+ }
+ else
+ {
+ port = 80;
+ }
+ host = pa.getword();
+ if (strstr(host.c_str(),":"))
+ {
+ Parse pa(host,":");
+ pa.getword(host);
+ port = static_cast<port_t>(pa.getvalue());
+ }
+ url = "/" + pa.getrest();
+ {
+ Parse pa(url,"/");
+ std::string tmp = pa.getword();
+ while (tmp.size())
+ {
+ file = tmp;
+ tmp = pa.getword();
+ }
+ }
+} // url_this
+
+
+bool HTTPSocket::ResponseHeaderIsSet(const std::string& name)
+{
+ string_m::iterator it = m_response_header.find( Utility::ToLower(name) );
+ if (it != m_response_header.end())
+ {
+ return true;
+ }
+ std::list<std::pair<std::string, std::string> >::iterator it2;
+ for (it2 = m_response_header_append.begin(); it2 != m_response_header_append.end(); it2++)
+ {
+ std::pair<std::string, std::string>& ref = *it2;
+ if (ref.first == Utility::ToLower(name) )
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+
+#ifdef SOCKETS_NAMESPACE
+}
+#endif
+
+
diff --git a/Sockets/HTTPSocket.h b/Sockets/HTTPSocket.h
new file mode 100644
index 0000000..00bb305
--- /dev/null
+++ b/Sockets/HTTPSocket.h
@@ -0,0 +1,152 @@
+/** \file HTTPSocket.h Class HTTPSocket definition.
+ ** \date 2004-04-06
+ ** \author grymse@alhem.net
+**/
+/*
+Copyright (C) 2004-2007 Anders Hedstrom
+
+This library is made available under the terms of the GNU GPL.
+
+If you would like to use this library in a closed-source application,
+a separate license agreement is available. For information about
+the closed-source license agreement for the C++ sockets library,
+please visit http://www.alhem.net/Sockets/license.html and/or
+email license@alhem.net.
+
+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.
+*/
+#ifndef _SOCKETS_HTTPSocket_H
+#define _SOCKETS_HTTPSocket_H
+
+#include "sockets-config.h"
+#include <map>
+#include "TcpSocket.h"
+
+#ifdef SOCKETS_NAMESPACE
+namespace SOCKETS_NAMESPACE {
+#endif
+
+/** \defgroup http HTTP Sockets */
+/** HTTP request/response base class.
+ \ingroup http */
+class HTTPSocket : public TcpSocket
+{
+ /** map to hold http header values. */
+ typedef std::map<std::string,std::string> string_m;
+public:
+ HTTPSocket(ISocketHandler& );
+ ~HTTPSocket();
+
+ void OnRawData(const char *buf,size_t len);
+ void OnLine(const std::string& line);
+
+ /** Callback executes when first line has been received.
+ GetMethod, GetUrl/GetUri, and GetHttpVersion are valid when this callback is executed. */
+ virtual void OnFirst() = 0;
+ /** For each header line this callback is executed.
+ \param key Http header name
+ \param value Http header value */
+ virtual void OnHeader(const std::string& key,const std::string& value) = 0;
+ /** Callback fires when all http headers have been received. */
+ virtual void OnHeaderComplete() = 0;
+ /** Chunk of http body data recevied. */
+ virtual void OnData(const char *,size_t) = 0;
+
+ /** Get http method from incoming request, ie GET/POST/PUT etc */
+ const std::string& GetMethod();
+ /** Set http method to be used in request. */
+ void SetMethod(const std::string& x);
+ /** Get url from request. */
+ const std::string& GetUrl();
+ /** Set url to be used in outgoing request. */
+ void SetUrl(const std::string& x);
+ /** Get part of url before '?' character. */
+ const std::string& GetUri();
+ /** Now why would I need this when there is a SetUrl method? */
+ void SetUri(const std::string& x);
+ /** Get part of url after '?' character. */
+ const std::string& GetQueryString();
+ /** Get http version from incoming request/response. */
+ const std::string& GetHttpVersion();
+ /** Get http status from incoming response. */
+ const std::string& GetStatus();
+ /** Get http statustext from incoming response. */
+ const std::string& GetStatusText();
+ /** Incoming header has been identified as a request (method url http_version\r\n). */
+ bool IsRequest();
+ /** Incoming header has been identified as a response (http_version status status_text\r\n). */
+ bool IsResponse();
+ /** Set http version to be used in outgoing request/response. */
+ void SetHttpVersion(const std::string& x);
+ /** Set http status for outgoing response. */
+ void SetStatus(const std::string& x);
+ /** Set http statustext for outgoing response. */
+ void SetStatusText(const std::string& x);
+ /** Add (and replace if exists) http header. */
+ void AddResponseHeader(const std::string& x,const std::string& y);
+ /** Add (and replace if exists) http header. */
+ void AddResponseHeader(const std::string& x,const char *format, ...);
+ /** Add http header. */
+ void AppendResponseHeader(const std::string& x,const std::string& y);
+ /** See if http header 'name' has been set. */
+ bool ResponseHeaderIsSet(const std::string& name);
+ /** Send response prepared with calls to methods SetHttpVersion, SetStatus, SetStatusText,
+ and AddResponseHeader. */
+ void SendResponse();
+ /** Send request prepared with calls to methods SetMethod, SetUrl, SetHttpVersion,
+ and AddResponseHeader. */
+ void SendRequest();
+
+ /** Implement this to return your own User-agent string. */
+ virtual std::string MyUseragent();
+
+ /** Parse url. If protocol is https, EnableSSL() will be called. */
+ void url_this(const std::string& url_in,std::string& protocol,std::string& host,port_t& port,std::string& url,std::string& file);
+
+protected:
+ HTTPSocket(const HTTPSocket& s) : TcpSocket(s) {}
+ /** Reset state of socket to sucessfully implement keep-alive. */
+ virtual void Reset();
+
+private:
+ HTTPSocket& operator=(const HTTPSocket& ) { return *this; }
+ bool m_first;
+ bool m_header;
+ std::string m_line;
+ std::string m_method;
+ std::string m_url;
+ std::string m_uri;
+ std::string m_query_string;
+ std::string m_http_version;
+ std::string m_status;
+ std::string m_status_text;
+ bool m_request;
+ bool m_response;
+ string_m m_response_header;
+ size_t m_body_size_left;
+ bool m_b_http_1_1;
+ bool m_b_keepalive;
+ std::list<std::pair<std::string, std::string> > m_response_header_append;
+};
+
+
+
+
+#ifdef SOCKETS_NAMESPACE
+}
+#endif
+
+#endif // _SOCKETS_HTTPSocket_H
+
diff --git a/Sockets/HttpBaseSocket.cpp b/Sockets/HttpBaseSocket.cpp
new file mode 100644
index 0000000..6f05b2e
--- /dev/null
+++ b/Sockets/HttpBaseSocket.cpp
@@ -0,0 +1,204 @@
+/**
+ ** \file AjpBaseSocket.cpp
+ ** \date 2007-10-05
+ ** \author grymse@alhem.net
+**/
+/*
+Copyright (C) 2007 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 _MSC_VER
+#pragma warning(disable:4786)
+#endif
+#include "HttpBaseSocket.h"
+#include "IFile.h"
+#include "Utility.h"
+#include "HttpResponse.h"
+
+#ifdef SOCKETS_NAMESPACE
+namespace SOCKETS_NAMESPACE {
+#endif
+
+#ifdef _DEBUG
+#define DEB(x) x
+#else
+#define DEB(x)
+#endif
+
+
+HttpBaseSocket::HttpBaseSocket(ISocketHandler& h)
+:HTTPSocket(h)
+,m_res_file(NULL)
+,m_b_keepalive(false)
+{
+}
+
+
+HttpBaseSocket::~HttpBaseSocket()
+{
+}
+
+
+void HttpBaseSocket::OnFirst()
+{
+DEB(fprintf(stderr, " %s %s %s\n", GetMethod().c_str(), GetUri().c_str(), GetHttpVersion().c_str());)
+ m_req.SetHttpMethod( GetMethod() );
+ m_req.SetUri( GetUri() );
+ m_req.SetHttpVersion( GetHttpVersion() );
+
+ m_req.SetAttribute("query_string", GetQueryString() );
+
+ m_req.SetRemoteAddr( GetRemoteAddress() );
+ m_req.SetRemoteHost( "" ); // %!
+ m_req.SetServerName( GetSockAddress() );
+ m_req.SetServerPort( GetSockPort() );
+}
+
+
+void HttpBaseSocket::OnHeader(const std::string& key,const std::string& value)
+{
+DEB(fprintf(stderr, " (request)OnHeader %s: %s\n", key.c_str(), value.c_str());)
+ if (Utility::ToLower(key) == "cookie")
+ m_req.AddCookie(value);
+ else
+ m_req.SetHeader(key, value);
+}
+
+
+void HttpBaseSocket::OnHeaderComplete()
+{
+ m_body_size_left = atol( m_req.Header("content-length").c_str() );
+ if (m_body_size_left > 0)
+ {
+ m_req.InitBody( m_body_size_left );
+ }
+ else
+ {
+ // execute
+ Execute();
+ }
+}
+
+
+void HttpBaseSocket::OnData(const char *buf,size_t sz)
+{
+ m_req.Write( buf, sz );
+ m_body_size_left -= sz;
+ if (!m_body_size_left)
+ {
+ m_req.CloseBody();
+
+ // execute
+ Execute();
+ }
+}
+
+
+// --------------------------------------------------------------------------------------
+void HttpBaseSocket::Execute()
+{
+ // parse form data / query_string and cookie header if available
+ m_req.ParseBody();
+
+ // prepare page
+ OnExec( m_req );
+
+DEB(printf(" *** http version: %s\n", m_req.HttpVersion().c_str());
+printf(" *** connection: %s\n", m_req.Header("connection").c_str());)
+ if ( !(m_req.HttpVersion().size() > 4 && m_req.HttpVersion().substr(m_req.HttpVersion().size() - 4) == "/1.1") ||
+ m_req.Header("connection") == "close")
+ {
+ m_b_keepalive = false;
+DEB(printf(" *** keepalive: false\n");)
+ }
+ else
+ {
+ m_b_keepalive = true;
+DEB(printf(" *** keepalive: true\n");)
+ }
+ m_req.Reset();
+ Reset();
+}
+
+
+// --------------------------------------------------------------------------------------
+void HttpBaseSocket::Respond(const HttpResponse& res)
+{
+// res.SetHeader("connection", "close");
+
+ SetHttpVersion( res.HttpVersion() );
+ SetStatus( Utility::l2string(res.HttpStatusCode()) );
+ SetStatusText( res.HttpStatusMsg() );
+
+ if (!ResponseHeaderIsSet("content-length"))
+ {
+ AddResponseHeader( "content-length", Utility::l2string( res.GetFile().size() ) );
+ }
+ for (std::map<std::string, std::string>::const_iterator it = res.Headers().begin(); it != res.Headers().end(); ++it)
+ {
+ AddResponseHeader( it -> first, it -> second );
+ }
+ std::list<std::string> vec = res.CookieNames();
+ for (std::list<std::string>::iterator it2 = vec.begin(); it2 != vec.end(); it2++)
+ {
+ AppendResponseHeader( "set-cookie", res.Cookie(*it2) );
+ }
+ SendResponse();
+
+ m_res_file = &res.GetFile();
+
+ OnTransferLimit();
+}
+
+
+// --------------------------------------------------------------------------------------
+void HttpBaseSocket::OnTransferLimit()
+{
+ char msg[32768];
+ size_t n = m_res_file -> fread(msg, 1, 32768);
+ while (n > 0)
+ {
+ SendBuf( msg, n );
+ if (GetOutputLength() > 1)
+ {
+ SetTransferLimit( 1 );
+ break;
+ }
+ n = m_res_file -> fread(msg, 1, 32768);
+ }
+ if (!GetOutputLength())
+ {
+ if (!m_b_keepalive)
+ {
+ SetCloseAndDelete();
+ }
+ }
+}
+
+
+// --------------------------------------------------------------------------------------
+void HttpBaseSocket::Reset()
+{
+ HTTPSocket::Reset();
+ m_body_size_left = 0;
+}
+
+
+#ifdef SOCKETS_NAMESPACE
+} // namespace SOCKETS_NAMESPACE {
+#endif
+
+
diff --git a/Sockets/HttpBaseSocket.h b/Sockets/HttpBaseSocket.h
new file mode 100644
index 0000000..8ce4ad8
--- /dev/null
+++ b/Sockets/HttpBaseSocket.h
@@ -0,0 +1,76 @@
+/**
+ ** \file HttpBaseSocket.h
+ ** \date 2007-10-05
+ ** \author grymse@alhem.net
+**/
+/*
+Copyright (C) 2007 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.
+*/
+#ifndef _HttpBaseSocket_H
+#define _HttpBaseSocket_H
+
+#include "HTTPSocket.h"
+#include "HttpRequest.h"
+#include "IHttpServer.h"
+
+#ifdef SOCKETS_NAMESPACE
+namespace SOCKETS_NAMESPACE {
+#endif
+
+
+class HttpResponse;
+
+class HttpBaseSocket : public HTTPSocket, public IHttpServer
+{
+public:
+ HttpBaseSocket(ISocketHandler& h);
+ ~HttpBaseSocket();
+
+ void OnFirst();
+ void OnHeader(const std::string& key,const std::string& value);
+ void OnHeaderComplete();
+ void OnData(const char *,size_t);
+
+ // implements IHttpServer::Respond
+ void Respond(const HttpResponse& res);
+
+ void OnTransferLimit();
+
+protected:
+ HttpBaseSocket(const HttpBaseSocket& s) : HTTPSocket(s) {} // copy constructor
+ //
+ HttpRequest m_req;
+ void Reset();
+
+private:
+ HttpBaseSocket& operator=(const HttpBaseSocket& ) { return *this; } // assignment operator
+ void Execute();
+ //
+ size_t m_body_size_left;
+ const IFile *m_res_file;
+ bool m_b_keepalive;
+};
+
+
+
+
+#ifdef SOCKETS_NAMESPACE
+} // namespace SOCKETS_NAMESPACE {
+#endif
+
+#endif // _HttpBaseSocket_H
+
diff --git a/Sockets/HttpClientSocket.cpp b/Sockets/HttpClientSocket.cpp
new file mode 100644
index 0000000..c6f43e4
--- /dev/null
+++ b/Sockets/HttpClientSocket.cpp
@@ -0,0 +1,277 @@
+/**
+ ** \file HttpClientSocket.cpp
+ ** \date 2006-04-20
+ ** \author grymse@alhem.net
+**/
+/*
+Copyright (C) 2007 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 _MSC_VER
+#pragma warning(disable:4786)
+#endif
+#include "HttpClientSocket.h"
+#include "StdLog.h"
+#include "ISocketHandler.h"
+#include "Utility.h"
+
+
+#ifdef SOCKETS_NAMESPACE
+namespace SOCKETS_NAMESPACE {
+#endif
+
+
+HttpClientSocket::HttpClientSocket(ISocketHandler& h)
+:HTTPSocket(h)
+,m_data_ptr(NULL)
+,m_data_size(0)
+,m_content_length(0)
+,m_data_ptr_set(false)
+,m_fil(NULL)
+,m_content_ptr(0)
+,m_b_complete(false)
+,m_b_close_when_complete(false)
+{
+}
+
+
+HttpClientSocket::HttpClientSocket(ISocketHandler& h,const std::string& url_in)
+:HTTPSocket(h)
+,m_data_ptr(NULL)
+,m_data_size(0)
+,m_content_length(0)
+,m_data_ptr_set(false)
+,m_fil(NULL)
+,m_content_ptr(0)
+,m_b_complete(false)
+,m_b_close_when_complete(false)
+{
+ std::string url;
+ url_this(url_in, m_protocol, m_host, m_port, url, m_url_filename);
+ SetUrl( url );
+}
+
+
+HttpClientSocket::~HttpClientSocket()
+{
+ if (m_data_ptr && !m_data_ptr_set)
+ {
+ delete[] m_data_ptr;
+ }
+ if (m_fil)
+ {
+ fclose(m_fil);
+ }
+}
+
+
+void HttpClientSocket::OnFirst()
+{
+ if (!IsResponse())
+ {
+ Handler().LogError(this, "OnFirst", 0, "Response expected but not received - aborting", LOG_LEVEL_FATAL);
+ SetCloseAndDelete();
+ }
+ m_content = GetHttpVersion() + " " + GetStatus() + " " + GetStatusText() + "\r\n";
+}
+
+
+void HttpClientSocket::OnHeader(const std::string& key,const std::string& value)
+{
+ m_content += key + ": " + value + "\r\n";
+ if (!strcasecmp(key.c_str(), "content-length"))
+ {
+ m_content_length = atoi(value.c_str());
+ }
+ else
+ if (!strcasecmp(key.c_str(), "content-type"))
+ {
+ m_content_type = value;
+ }
+}
+
+
+void HttpClientSocket::OnHeaderComplete()
+{
+ if (m_filename.size())
+ {
+ m_fil = fopen(m_filename.c_str(), "wb");
+ }
+ else
+ if (!m_data_ptr && m_content_length)
+ {
+ m_data_ptr = new unsigned char[m_content_length];
+ m_data_size = m_content_length;
+ }
+}
+
+
+void HttpClientSocket::OnData(const char *buf,size_t len)
+{
+ if (m_fil)
+ {
+ fwrite(buf, 1, len, m_fil);
+ }
+ else
+ if (m_data_ptr)
+ {
+ if (m_content_ptr + len > m_data_size)
+ {
+ Handler().LogError(this, "OnData", -1, "content buffer overflow", LOG_LEVEL_ERROR);
+ }
+ else
+ {
+ memcpy(m_data_ptr + m_content_ptr, buf, len);
+ }
+ }
+ m_content_ptr += len;
+ if (m_content_ptr == m_content_length && m_content_length)
+ {
+ if (m_fil)
+ {
+ fclose(m_fil);
+ m_fil = NULL;
+ }
+ m_b_complete = true;
+ OnContent();
+ if (m_b_close_when_complete)
+ {
+ SetCloseAndDelete();
+ }
+ }
+}
+
+
+void HttpClientSocket::OnDelete()
+{
+ if (!m_b_complete)
+ {
+ if (m_fil)
+ {
+ fclose(m_fil);
+ m_fil = NULL;
+ }
+ m_b_complete = true;
+ OnContent();
+ }
+}
+
+
+void HttpClientSocket::SetFilename(const std::string& x)
+{
+ m_filename = x;
+}
+
+
+void HttpClientSocket::SetDataPtr(unsigned char *buf,size_t len)
+{
+ m_data_ptr = buf;
+ m_data_size = len;
+ m_data_ptr_set = true;
+}
+
+
+const std::string& HttpClientSocket::GetContent()
+{
+ return m_content;
+}
+
+
+size_t HttpClientSocket::GetContentLength()
+{
+ return m_content_length;
+}
+
+
+size_t HttpClientSocket::GetContentPtr()
+{
+ return m_content_ptr;
+}
+
+
+size_t HttpClientSocket::GetPos()
+{
+ return m_content_ptr;
+}
+
+
+bool HttpClientSocket::Complete()
+{
+ return m_b_complete;
+}
+
+
+const unsigned char *HttpClientSocket::GetDataPtr() const
+{
+ return m_data_ptr;
+}
+
+
+void HttpClientSocket::OnContent()
+{
+}
+
+
+void HttpClientSocket::SetCloseOnComplete(bool x)
+{
+ m_b_close_when_complete = x;
+}
+
+
+const std::string& HttpClientSocket::GetUrlProtocol()
+{
+ return m_protocol;
+}
+
+
+const std::string& HttpClientSocket::GetUrlHost()
+{
+ return m_host;
+}
+
+
+port_t HttpClientSocket::GetUrlPort()
+{
+ return m_port;
+}
+
+
+const std::string& HttpClientSocket::GetUrlFilename()
+{
+ return m_url_filename;
+}
+
+
+const std::string& HttpClientSocket::GetContentType()
+{
+ return m_content_type;
+}
+
+
+void HttpClientSocket::Url(const std::string& url_in,std::string& host,port_t& port)
+{
+ std::string url;
+ url_this(url_in, m_protocol, m_host, m_port, url, m_url_filename);
+ SetUrl(url);
+ host = GetUrlHost();
+ port = GetUrlPort();
+}
+
+
+#ifdef SOCKETS_NAMESPACE
+} // namespace SOCKETS_NAMESPACE {
+#endif
+
diff --git a/Sockets/HttpClientSocket.h b/Sockets/HttpClientSocket.h
new file mode 100644
index 0000000..dc307a9
--- /dev/null
+++ b/Sockets/HttpClientSocket.h
@@ -0,0 +1,121 @@
+/**
+ ** \file HttpClientSocket.h
+ ** \date 2006-04-20
+ ** \author grymse@alhem.net
+**/
+/*
+Copyright (C) 2007 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.
+*/
+#ifndef _SOCKETS_HttpClientSocket_H
+#define _SOCKETS_HttpClientSocket_H
+
+#include "sockets-config.h"
+#include "HTTPSocket.h"
+
+#ifdef SOCKETS_NAMESPACE
+namespace SOCKETS_NAMESPACE {
+#endif
+
+/** Get http response to file or memory.
+ \ingroup http */
+class HttpClientSocket : public HTTPSocket
+{
+public:
+ HttpClientSocket(ISocketHandler&);
+ HttpClientSocket(ISocketHandler&,const std::string& url_in);
+ ~HttpClientSocket();
+
+ /** Parse url to protocol,host,port,url and file. */
+ void Url(const std::string& url_in,std::string& host,port_t& port);
+
+ void OnFirst();
+ void OnHeader(const std::string&,const std::string&);
+ void OnHeaderComplete();
+ void OnData(const char *,size_t);
+ void OnDelete();
+
+ /** New callback method fires when all data is received. */
+ virtual void OnContent();
+
+ /** Write response to this file */
+ void SetFilename(const std::string& );
+ const std::string& Filename() const { return m_filename; }
+
+ /** Store response in this buffer. */
+ void SetDataPtr(unsigned char *,size_t);
+
+ /** Get response headers. */
+ const std::string& GetContent();
+
+ /** Get size of response body. */
+ size_t GetContentLength();
+
+ /** Get content type from response header. */
+ const std::string& GetContentType();
+
+ /** Get size of received response body. */
+ size_t GetContentPtr();
+ /** Get size of received response body. */
+ size_t GetPos();
+
+ /** Complete response has been received. */
+ bool Complete();
+
+ /** Get ptr to response data buffer. */
+ const unsigned char *GetDataPtr() const;
+
+ /** Close socket when response received. */
+ void SetCloseOnComplete(bool = true);
+
+ /** Get protocol used from url. */
+ const std::string& GetUrlProtocol();
+ /** Get hostname from url. */
+ const std::string& GetUrlHost();
+ /** Get port from url. */
+ port_t GetUrlPort();
+ /** Get filename part of url. */
+ const std::string& GetUrlFilename();
+
+protected:
+ HttpClientSocket(const HttpClientSocket& s) : HTTPSocket(s) {} // copy constructor
+ HttpClientSocket& operator=(const HttpClientSocket& ) { return *this; } // assignment operator
+private:
+ std::string m_filename; ///< Filename to write response to
+ unsigned char *m_data_ptr; ///< Ptr to buffer where to store response
+ size_t m_data_size; ///< Max size of data buffer
+ size_t m_content_length; ///< Content-length header received from remote
+ std::string m_content; ///< Received http headers
+ bool m_data_ptr_set; ///< Buffer set from outside, do not delete
+ FILE *m_fil; ///< Output file
+ size_t m_content_ptr; ///< Number of bytes received from body
+ bool m_b_complete; ///< The entire content-length number of bytes has been received
+ bool m_b_close_when_complete; ///< Close when the full response has been received
+ std::string m_protocol; ///< Protocol part of url_in
+ std::string m_host; ///< Hostname from url_in
+ port_t m_port; ///< Port from url_in
+ std::string m_url_filename; ///< Filename from url_in
+ std::string m_content_type; ///< Content-type: header from response
+};
+
+
+
+
+#ifdef SOCKETS_NAMESPACE
+} // namespace SOCKETS_NAMESPACE {
+#endif
+#endif // _SOCKETS_HttpClientSocket_H
+
diff --git a/Sockets/HttpDebugSocket.cpp b/Sockets/HttpDebugSocket.cpp
new file mode 100644
index 0000000..70bf75b
--- /dev/null
+++ b/Sockets/HttpDebugSocket.cpp
@@ -0,0 +1,125 @@
+/** \file HttpDebugSocket.cpp
+ ** \date 2004-10-08
+**/
+/*
+Copyright (C) 2004-2007 Anders Hedström (grymse@alhem.net)
+
+This library is made available under the terms of the GNU GPL.
+
+If you would like to use this library in a closed-source application,
+a separate license agreement is available. For information about
+the closed-source license agreement for the C++ sockets library,
+please visit http://www.alhem.net/Sockets/license.html and/or
+email license@alhem.net.
+
+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 _MSC_VER
+#pragma warning(disable:4786)
+#endif
+#include "HttpDebugSocket.h"
+#include "Utility.h"
+#include "ISocketHandler.h"
+
+
+#ifdef SOCKETS_NAMESPACE
+namespace SOCKETS_NAMESPACE {
+#endif
+
+
+HttpDebugSocket::HttpDebugSocket(ISocketHandler& h) : HTTPSocket(h)
+,m_content_length(0)
+,m_read_ptr(0)
+{
+}
+
+
+HttpDebugSocket::~HttpDebugSocket()
+{
+}
+
+
+void HttpDebugSocket::Init()
+{
+ if (GetParent() -> GetPort() == 443)
+ {
+#ifdef HAVE_OPENSSL
+ EnableSSL();
+#else
+ Handler().LogError(this, "url_this", -1, "SSL not available", LOG_LEVEL_WARNING);
+#endif
+ }
+}
+
+
+void HttpDebugSocket::OnFirst()
+{
+ Send(
+ "HTTP/1.1 200 OK\n"
+ "Content-type: text/html\n"
+ "Connection: close\n"
+ "Server: HttpDebugSocket/1.0\n"
+ "\n");
+ Send(
+ "<html><head><title>Echo Request</title></head>"
+ "<body><h3>Request Header</h3>");
+ Send( "<form method='post' action='/test_post'>"
+ "<input type='text' name='text' value='test text'><br>"
+ "<input type='submit' name='submit' value=' OK '></form>");
+ Send( "<pre style='background: #e0e0e0'>");
+ Send(GetMethod() + " " + GetUrl() + " " + GetHttpVersion() + "\n");
+}
+
+
+void HttpDebugSocket::OnHeader(const std::string& key,const std::string& value)
+{
+ if (!strcasecmp(key.c_str(),"content-length"))
+ m_content_length = atoi(value.c_str());
+
+ Send(key + ": " + value + "\n");
+}
+
+
+void HttpDebugSocket::OnHeaderComplete()
+{
+ if (m_content_length)
+ {
+ Send("</pre><h3>Request Body</h3><pre style='background: #e0e0e0'>");
+ }
+ else
+ {
+ Send("</pre><hr></body></html>");
+ SetCloseAndDelete();
+ }
+}
+
+
+void HttpDebugSocket::OnData(const char *p,size_t l)
+{
+ SendBuf(p,l);
+ m_read_ptr += (int)l;
+ if (m_read_ptr >= m_content_length && m_content_length)
+ {
+ Send("</pre><hr></body></html>");
+ SetCloseAndDelete();
+ }
+}
+
+
+#ifdef SOCKETS_NAMESPACE
+}
+#endif
+
+
diff --git a/Sockets/HttpDebugSocket.h b/Sockets/HttpDebugSocket.h
new file mode 100644
index 0000000..f905904
--- /dev/null
+++ b/Sockets/HttpDebugSocket.h
@@ -0,0 +1,70 @@
+/** \file HttpDebugSocket.h
+ ** \date 2004-09-27
+**/
+/*
+Copyright (C) 2004-2007 Anders Hedström (grymse@alhem.net)
+
+This library is made available under the terms of the GNU GPL.
+
+If you would like to use this library in a closed-source application,
+a separate license agreement is available. For information about
+the closed-source license agreement for the C++ sockets library,
+please visit http://www.alhem.net/Sockets/license.html and/or
+email license@alhem.net.
+
+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.
+*/
+#ifndef _SOCKETS_HttpDebugSocket_H
+#define _SOCKETS_HttpDebugSocket_H
+
+#include "sockets-config.h"
+#include "HTTPSocket.h"
+
+#ifdef SOCKETS_NAMESPACE
+namespace SOCKETS_NAMESPACE {
+#endif
+
+class ISocketHandler;
+
+/** HTTP request "echo" class. This class echoes a http request/body
+with a html formatted page.
+ \ingroup http */
+class HttpDebugSocket : public HTTPSocket
+{
+public:
+ HttpDebugSocket(ISocketHandler&);
+ ~HttpDebugSocket();
+
+ void Init();
+
+ void OnFirst();
+ void OnHeader(const std::string& key,const std::string& value);
+ void OnHeaderComplete();
+ void OnData(const char *,size_t);
+
+private:
+ HttpDebugSocket(const HttpDebugSocket& s) : HTTPSocket(s) {} // copy constructor
+ HttpDebugSocket& operator=(const HttpDebugSocket& ) { return *this; } // assignment operator
+ int m_content_length;
+ int m_read_ptr;
+};
+
+
+#ifdef SOCKETS_NAMESPACE
+}
+#endif
+
+#endif // _SOCKETS_HttpDebugSocket_H
+
diff --git a/Sockets/HttpGetSocket.cpp b/Sockets/HttpGetSocket.cpp
new file mode 100644
index 0000000..fe5e3d5
--- /dev/null
+++ b/Sockets/HttpGetSocket.cpp
@@ -0,0 +1,114 @@
+/** \file HttpGetSocket.cpp
+ ** \date 2004-02-13
+ ** \author grymse@alhem.net
+**/
+/*
+Copyright (C) 2004-2007 Anders Hedstrom
+
+This library is made available under the terms of the GNU GPL.
+
+If you would like to use this library in a closed-source application,
+a separate license agreement is available. For information about
+the closed-source license agreement for the C++ sockets library,
+please visit http://www.alhem.net/Sockets/license.html and/or
+email license@alhem.net.
+
+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
+#ifdef _MSC_VER
+#pragma warning(disable:4786)
+#endif
+#else
+#include <errno.h>
+#endif
+#include "Utility.h"
+#include "Parse.h"
+#include "ISocketHandler.h"
+#include "HttpGetSocket.h"
+
+
+#ifdef SOCKETS_NAMESPACE
+namespace SOCKETS_NAMESPACE {
+#endif
+
+
+HttpGetSocket::HttpGetSocket(ISocketHandler& h) : HttpClientSocket(h)
+{
+}
+
+
+HttpGetSocket::HttpGetSocket(ISocketHandler& h,const std::string& url_in,const std::string& to_file) : HttpClientSocket(h, url_in)
+{
+ if (to_file.size())
+ {
+ SetFilename(to_file);
+ }
+ if (!Open(GetUrlHost(),GetUrlPort()))
+ {
+ if (!Connecting())
+ {
+ Handler().LogError(this, "HttpGetSocket", -1, "connect() failed miserably", LOG_LEVEL_FATAL);
+ SetCloseAndDelete();
+ }
+ }
+}
+
+
+HttpGetSocket::HttpGetSocket(ISocketHandler& h,const std::string& host,port_t port,const std::string& url,const std::string& to_file) : HttpClientSocket(h)
+{
+ SetUrl(url);
+ if (to_file.size())
+ {
+ SetFilename(to_file);
+ }
+ if (!Open(host, port))
+ {
+ if (!Connecting())
+ {
+ Handler().LogError(this, "HttpGetSocket", -1, "connect() failed miserably", LOG_LEVEL_FATAL);
+ SetCloseAndDelete();
+ }
+ }
+}
+
+
+HttpGetSocket::~HttpGetSocket()
+{
+}
+
+
+void HttpGetSocket::OnConnect()
+{
+ SetMethod( "GET" );
+ AddResponseHeader( "Accept", "text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,video/x-mng,image/png,image/jpeg,image/gif;q=0.2,*/*;q=0.1");
+ AddResponseHeader( "Accept-Language", "en-us,en;q=0.5");
+ AddResponseHeader( "Accept-Encoding", "gzip,deflate");
+ AddResponseHeader( "Accept-Charset", "ISO-8859-1,utf-8;q=0.7,*;q=0.7");
+ AddResponseHeader( "User-agent", MyUseragent() );
+
+ if (GetUrlPort() != 80 && GetUrlPort() != 443)
+ AddResponseHeader( "Host", GetUrlHost() + ":" + Utility::l2string(GetUrlPort()) );
+ else
+ AddResponseHeader( "Host", GetUrlHost() );
+ SendRequest();
+}
+
+
+#ifdef SOCKETS_NAMESPACE
+}
+#endif
+
+
diff --git a/Sockets/HttpGetSocket.h b/Sockets/HttpGetSocket.h
new file mode 100644
index 0000000..beb1097
--- /dev/null
+++ b/Sockets/HttpGetSocket.h
@@ -0,0 +1,66 @@
+/** \file HttpGetSocket.h
+ ** \date 2004-02-13
+ ** \author grymse@alhem.net
+**/
+/*
+Copyright (C) 2004-2007 Anders Hedstrom
+
+This library is made available under the terms of the GNU GPL.
+
+If you would like to use this library in a closed-source application,
+a separate license agreement is available. For information about
+the closed-source license agreement for the C++ sockets library,
+please visit http://www.alhem.net/Sockets/license.html and/or
+email license@alhem.net.
+
+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.
+*/
+#ifndef _SOCKETS_HttpGetSocket_H
+#define _SOCKETS_HttpGetSocket_H
+
+#include "sockets-config.h"
+#include "HttpClientSocket.h"
+
+#ifdef SOCKETS_NAMESPACE
+namespace SOCKETS_NAMESPACE {
+#endif
+
+
+/** Get http page.
+ \ingroup http */
+class HttpGetSocket : public HttpClientSocket
+{
+public:
+ HttpGetSocket(ISocketHandler&);
+ HttpGetSocket(ISocketHandler&,const std::string& url,const std::string& to_file = "");
+ HttpGetSocket(ISocketHandler&,const std::string& host,port_t port,const std::string& url,const std::string& to_file = "");
+ ~HttpGetSocket();
+
+ void OnConnect();
+
+protected:
+ HttpGetSocket& operator=(const HttpGetSocket& ) { return *this; }
+ HttpGetSocket(const HttpGetSocket& s) : HttpClientSocket(s) {}
+};
+
+
+
+
+#ifdef SOCKETS_NAMESPACE
+}
+#endif
+
+#endif // _SOCKETS_HttpGetSocket_H
+
diff --git a/Sockets/HttpPostSocket.cpp b/Sockets/HttpPostSocket.cpp
new file mode 100644
index 0000000..a72b8cf
--- /dev/null
+++ b/Sockets/HttpPostSocket.cpp
@@ -0,0 +1,294 @@
+/** \file HttpPostSocket.cpp
+ ** \date 2004-10-30
+ ** \author grymse@alhem.net
+**/
+/*
+Copyright (C) 2004-2007 Anders Hedstrom
+
+This library is made available under the terms of the GNU GPL.
+
+If you would like to use this library in a closed-source application,
+a separate license agreement is available. For information about
+the closed-source license agreement for the C++ sockets library,
+please visit http://www.alhem.net/Sockets/license.html and/or
+email license@alhem.net.
+
+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
+#ifdef _MSC_VER
+#pragma warning(disable:4786)
+#pragma warning(disable:4503)
+#endif
+#else
+#include <errno.h>
+#include <ctype.h>
+#endif
+#include "ISocketHandler.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+#include "Parse.h"
+#include "Utility.h"
+#include "Lock.h"
+
+#include "HttpPostSocket.h"
+
+
+#ifdef SOCKETS_NAMESPACE
+namespace SOCKETS_NAMESPACE {
+#endif
+
+
+int HttpPostSocket::m_boundary_count = 0;
+Mutex HttpPostSocket::m_boundary_mutex;
+
+
+HttpPostSocket::HttpPostSocket(ISocketHandler& h) : HttpClientSocket(h)
+,m_bMultipart(false)
+{
+}
+
+
+HttpPostSocket::HttpPostSocket(ISocketHandler& h,const std::string& url_in) : HttpClientSocket(h, url_in)
+,m_bMultipart(false)
+{
+ Lock lock(m_boundary_mutex);
+
+ m_boundary = "----";
+ for (int i = 0; i < 12; i++)
+ {
+ char c = m_boundary_count++ % 128;
+ while (!isalnum(c))
+ c = m_boundary_count++ % 128;
+ m_boundary += c;
+ }
+ m_boundary += "__" + Utility::l2string(m_boundary_count++);
+}
+
+
+HttpPostSocket::~HttpPostSocket()
+{
+}
+
+
+void HttpPostSocket::AddField(const std::string& name,const std::string& value)
+{
+ std::list<std::string> vec;
+ vec.push_back(value);
+ AddMultilineField(name, vec);
+}
+
+
+void HttpPostSocket::AddMultilineField(const std::string& name,std::list<std::string>& values)
+{
+ m_fields[name] = values;
+}
+
+
+void HttpPostSocket::AddFile(const std::string& name,const std::string& filename,const std::string& type)
+{
+ struct stat st;
+ if (!stat(filename.c_str(), &st))
+ {
+ m_files[name] = filename;
+ m_content_length[filename] = st.st_size;
+ m_content_type[filename] = type;
+ m_bMultipart = true;
+ }
+ else
+ {
+ Handler().LogError(this, "AddFile", Errno, StrError(Errno), LOG_LEVEL_FATAL);
+ SetCloseAndDelete();
+ }
+}
+
+
+void HttpPostSocket::Open()
+{
+ // why do I have to specify TcpSocket:: to get to the Open() method??
+ TcpSocket::Open(GetUrlHost(), GetUrlPort());
+}
+
+
+void HttpPostSocket::OnConnect()
+{
+ if (m_bMultipart)
+ {
+ DoMultipartPost();
+ }
+ else
+ {
+ std::string body;
+
+ // only fields, no files, add urlencoding
+ for (std::map<std::string,std::list<std::string> >::iterator it = m_fields.begin(); it != m_fields.end(); it++)
+ {
+ std::string name = (*it).first;
+ std::list<std::string>& ref = (*it).second;
+ if (body.size())
+ {
+ body += '&';
+ }
+ body += name + "=";
+ bool first = true;
+ for (std::list<std::string>::iterator it = ref.begin(); it != ref.end(); it++)
+ {
+ std::string value = *it;
+ if (!first)
+ {
+ body += "%0d%0a"; // CRLF
+ }
+ body += Utility::rfc1738_encode(value);
+ first = false;
+ }
+ }
+
+ // build header, send body
+ SetMethod("POST");
+ SetHttpVersion( "HTTP/1.1" );
+ AddResponseHeader( "Host", GetUrlHost() ); // oops - this is actually a request header that we're adding..
+ AddResponseHeader( "User-agent", MyUseragent());
+ AddResponseHeader( "Accept", "text/html, text/plain, */*;q=0.01" );
+ AddResponseHeader( "Connection", "close" );
+ AddResponseHeader( "Content-type", "application/x-www-form-urlencoded" );
+ AddResponseHeader( "Content-length", Utility::l2string((long)body.size()) );
+ SendRequest();
+
+ // send body
+ Send( body );
+ }
+}
+
+
+void HttpPostSocket::DoMultipartPost()
+{
+ long length = 0; // calculate content_length of our post body
+ std::string tmp;
+
+ // fields
+ {
+ for (std::map<std::string,std::list<std::string> >::iterator it = m_fields.begin(); it != m_fields.end(); it++)
+ {
+ std::string name = (*it).first;
+ std::list<std::string>& ref = (*it).second;
+ tmp = "--" + m_boundary + "\r\n"
+ "content-disposition: form-data; name=\"" + name + "\"\r\n"
+ "\r\n";
+ for (std::list<std::string>::iterator it = ref.begin(); it != ref.end(); it++)
+ {
+ std::string value = *it;
+ tmp += value + "\r\n";
+ }
+ length += (long)tmp.size();
+ }
+ }
+
+ // files
+ {
+ for (std::map<std::string,std::string>::iterator it = m_files.begin(); it != m_files.end(); it++)
+ {
+ std::string name = (*it).first;
+ std::string filename = (*it).second;
+ long content_length = m_content_length[filename];
+ std::string content_type = m_content_type[filename];
+ tmp = "--" + m_boundary + "\r\n"
+ "content-disposition: form-data; name=\"" + name + "\"; filename=\"" + filename + "\"\r\n"
+ "content-type: " + content_type + "\r\n"
+ "\r\n";
+ length += (long)tmp.size();
+ length += content_length;
+ length += 2; // crlf after file
+ }
+ }
+
+ // end
+ tmp = "--" + m_boundary + "--\r\n";
+ length += (long)tmp.size();
+
+ // build header, send body
+ SetMethod("POST");
+ SetHttpVersion( "HTTP/1.1" );
+ AddResponseHeader( "Host", GetUrlHost() ); // oops - this is actually a request header that we're adding..
+ AddResponseHeader( "User-agent", MyUseragent());
+ AddResponseHeader( "Accept", "text/html, text/plain, */*;q=0.01" );
+ AddResponseHeader( "Connection", "close" );
+ AddResponseHeader( "Content-type", "multipart/form-data; boundary=" + m_boundary );
+ AddResponseHeader( "Content-length", Utility::l2string(length) );
+
+ SendRequest();
+
+ // send fields
+ {
+ for (std::map<std::string,std::list<std::string> >::iterator it = m_fields.begin(); it != m_fields.end(); it++)
+ {
+ std::string name = (*it).first;
+ std::list<std::string>& ref = (*it).second;
+ tmp = "--" + m_boundary + "\r\n"
+ "content-disposition: form-data; name=\"" + name + "\"\r\n"
+ "\r\n";
+ for (std::list<std::string>::iterator it = ref.begin(); it != ref.end(); it++)
+ {
+ std::string value = *it;
+ tmp += value + "\r\n";
+ }
+ Send( tmp );
+ }
+ }
+
+ // send files
+ {
+ for (std::map<std::string,std::string>::iterator it = m_files.begin(); it != m_files.end(); it++)
+ {
+ std::string name = (*it).first;
+ std::string filename = (*it).second;
+ std::string content_type = m_content_type[filename];
+ tmp = "--" + m_boundary + "\r\n"
+ "content-disposition: form-data; name=\"" + name + "\"; filename=\"" + filename + "\"\r\n"
+ "content-type: " + content_type + "\r\n"
+ "\r\n";
+ Send( tmp );
+ {
+ FILE *fil = fopen(filename.c_str(),"rb");
+ if (fil)
+ {
+ char slask[2000]; // for fread
+ size_t n;
+ while ((n = fread(slask, 1, 2000, fil)) > 0)
+ {
+ SendBuf(slask, n);
+ }
+ fclose(fil);
+ }
+ }
+ Send("\r\n");
+ }
+ }
+
+ // end of send
+ Send("--" + m_boundary + "--\r\n");
+}
+
+
+void HttpPostSocket::SetMultipart()
+{
+ m_bMultipart = true;
+}
+
+
+#ifdef SOCKETS_NAMESPACE
+}
+#endif
+
+
diff --git a/Sockets/HttpPostSocket.h b/Sockets/HttpPostSocket.h
new file mode 100644
index 0000000..7815da3
--- /dev/null
+++ b/Sockets/HttpPostSocket.h
@@ -0,0 +1,94 @@
+/** \file HttpPostSocket.h
+ ** \date 2004-10-30
+ ** \author grymse@alhem.net
+**/
+/*
+Copyright (C) 2004-2007 Anders Hedstrom
+
+This library is made available under the terms of the GNU GPL.
+
+If you would like to use this library in a closed-source application,
+a separate license agreement is available. For information about
+the closed-source license agreement for the C++ sockets library,
+please visit http://www.alhem.net/Sockets/license.html and/or
+email license@alhem.net.
+
+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.
+*/
+#ifndef _SOCKETS_HttpPostSocket_H
+#define _SOCKETS_HttpPostSocket_H
+
+#include "sockets-config.h"
+#include "HttpClientSocket.h"
+#include "Mutex.h"
+
+#ifdef SOCKETS_NAMESPACE
+namespace SOCKETS_NAMESPACE {
+#endif
+
+
+class ISocketHandler;
+
+/** Generate a http post request, get response.
+ \ingroup http */
+class HttpPostSocket : public HttpClientSocket
+{
+public:
+ HttpPostSocket(ISocketHandler&);
+ /* client constructor,
+ \param url_in = 'http://host:port/resource' */
+ HttpPostSocket(ISocketHandler&,const std::string& url_in);
+ ~HttpPostSocket();
+
+ // these must be specified before connecting / adding to handler
+ /** Add field to post. */
+ void AddField(const std::string& name,const std::string& value);
+ /** Add multiline field to post. */
+ void AddMultilineField(const std::string& name,std::list<std::string>& values);
+ /** Add file to post. */
+ void AddFile(const std::string& name,const std::string& filename,const std::string& type);
+
+ /** use this to post with content-type multipart/form-data.
+ // when adding a file to the post, this is the default and only content-type */
+ void SetMultipart();
+
+ /** connect to host:port derived from url in constructor */
+ void Open();
+
+ /** http put client implemented in OnConnect */
+ void OnConnect();
+
+private:
+ HttpPostSocket(const HttpPostSocket& s) : HttpClientSocket(s) {} // copy constructor
+ HttpPostSocket& operator=(const HttpPostSocket& ) { return *this; } // assignment operator
+ void DoMultipartPost();
+ //
+ std::map<std::string,std::list<std::string> > m_fields;
+ std::map<std::string,std::string> m_files;
+ std::string m_boundary;
+ std::map<std::string,long> m_content_length;
+ std::map<std::string,std::string> m_content_type;
+ bool m_bMultipart;
+static int m_boundary_count;
+static Mutex m_boundary_mutex;
+};
+
+
+#ifdef SOCKETS_NAMESPACE
+}
+#endif
+
+#endif // _SOCKETS_HttpPostSocket_H
+
diff --git a/Sockets/HttpPutSocket.cpp b/Sockets/HttpPutSocket.cpp
new file mode 100644
index 0000000..90ac7e4
--- /dev/null
+++ b/Sockets/HttpPutSocket.cpp
@@ -0,0 +1,125 @@
+/** \file HttpPutSocket.cpp
+ ** \date 2004-10-30
+ ** \author grymse@alhem.net
+**/
+/*
+Copyright (C) 2004-2007 Anders Hedstrom
+
+This library is made available under the terms of the GNU GPL.
+
+If you would like to use this library in a closed-source application,
+a separate license agreement is available. For information about
+the closed-source license agreement for the C++ sockets library,
+please visit http://www.alhem.net/Sockets/license.html and/or
+email license@alhem.net.
+
+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
+#ifdef _MSC_VER
+#pragma warning(disable:4786)
+#endif
+#else
+#include <errno.h>
+#endif
+#include "ISocketHandler.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include "Utility.h"
+#include "Parse.h"
+
+#include "HttpPutSocket.h"
+
+
+#ifdef SOCKETS_NAMESPACE
+namespace SOCKETS_NAMESPACE {
+#endif
+
+
+HttpPutSocket::HttpPutSocket(ISocketHandler& h) : HttpClientSocket(h)
+{
+}
+
+
+HttpPutSocket::HttpPutSocket(ISocketHandler& h,const std::string& url_in) : HttpClientSocket(h, url_in)
+{
+}
+
+
+HttpPutSocket::~HttpPutSocket()
+{
+}
+
+
+void HttpPutSocket::SetFile(const std::string& file)
+{
+ struct stat st;
+ if (!stat(file.c_str(), &st))
+ {
+ m_filename = file;
+ m_content_length = st.st_size;
+ }
+ else
+ {
+ Handler().LogError(this, "SetFile", Errno, StrError(Errno), LOG_LEVEL_FATAL);
+ SetCloseAndDelete();
+ }
+}
+
+
+void HttpPutSocket::SetContentType(const std::string& type)
+{
+ m_content_type = type;
+}
+
+
+
+void HttpPutSocket::Open()
+{
+ // why do I have to specify TcpSocket:: to get to the Open() method??
+ TcpSocket::Open(GetUrlHost(), GetUrlPort());
+}
+
+
+void HttpPutSocket::OnConnect()
+{
+ SetMethod( "PUT" );
+ SetHttpVersion( "HTTP/1.1" );
+ AddResponseHeader( "Host", GetUrlHost() );
+ AddResponseHeader( "Content-type", m_content_type );
+ AddResponseHeader( "Content-length", Utility::l2string(m_content_length) );
+ AddResponseHeader( "User-agent", MyUseragent() );
+ SendRequest();
+
+ FILE *fil = fopen(m_filename.c_str(), "rb");
+ if (fil)
+ {
+ size_t n;
+ char buf[32768];
+ while ((n = fread(buf, 1, 32768, fil)) > 0)
+ {
+ SendBuf(buf, n);
+ }
+ fclose(fil);
+ }
+}
+
+
+#ifdef SOCKETS_NAMESPACE
+}
+#endif
+
+
diff --git a/Sockets/HttpPutSocket.h b/Sockets/HttpPutSocket.h
new file mode 100644
index 0000000..cafc7b9
--- /dev/null
+++ b/Sockets/HttpPutSocket.h
@@ -0,0 +1,83 @@
+/** \file HttpPutSocket.h
+ ** \date 2004-10-30
+ ** \author grymse@alhem.net
+**/
+/*
+Copyright (C) 2004-2007 Anders Hedstrom
+
+This library is made available under the terms of the GNU GPL.
+
+If you would like to use this library in a closed-source application,
+a separate license agreement is available. For information about
+the closed-source license agreement for the C++ sockets library,
+please visit http://www.alhem.net/Sockets/license.html and/or
+email license@alhem.net.
+
+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.
+*/
+#ifndef _SOCKETS_HttpPutSocket_H
+#define _SOCKETS_HttpPutSocket_H
+
+#include "sockets-config.h"
+#include "HttpClientSocket.h"
+
+#ifdef SOCKETS_NAMESPACE
+namespace SOCKETS_NAMESPACE {
+#endif
+
+
+class ISocketHandler;
+
+/** Put http page.
+ \ingroup http */
+class HttpPutSocket : public HttpClientSocket
+{
+public:
+ HttpPutSocket(ISocketHandler&);
+ /** client constructor,
+ \param url_in = 'http://host:port/resource' */
+ HttpPutSocket(ISocketHandler&,const std::string& url_in);
+ ~HttpPutSocket();
+
+ // these must be specified before connecting / adding to handler
+ /** Set filename to send. */
+ void SetFile(const std::string& );
+ /** Set mimetype of file to send. */
+ void SetContentType(const std::string& );
+
+ /** connect to host:port derived from url in constructor */
+ void Open();
+
+ /** http put client implemented in OnConnect */
+ void OnConnect();
+
+private:
+ HttpPutSocket(const HttpPutSocket& s) : HttpClientSocket(s) {} // copy constructor
+ HttpPutSocket& operator=(const HttpPutSocket& ) { return *this; } // assignment operator
+ //
+ std::string m_filename;
+ std::string m_content_type;
+ long m_content_length;
+};
+
+
+
+
+#ifdef SOCKETS_NAMESPACE
+}
+#endif
+
+#endif // _SOCKETS_HttpPutSocket_H
+
diff --git a/Sockets/HttpRequest.cpp b/Sockets/HttpRequest.cpp
new file mode 100644
index 0000000..3909595
--- /dev/null
+++ b/Sockets/HttpRequest.cpp
@@ -0,0 +1,358 @@
+/**
+ ** \file HttpRequest.cpp
+ ** \date 2007-10-05
+ ** \author grymse@alhem.net
+**/
+/*
+Copyright (C) 2007 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 _MSC_VER
+#pragma warning(disable:4786)
+#endif
+#include "HttpRequest.h"
+#include "Utility.h"
+#include "MemFile.h"
+#include "HttpdForm.h"
+#include "HttpdCookies.h"
+#include "Parse.h"
+
+#ifdef SOCKETS_NAMESPACE
+namespace SOCKETS_NAMESPACE {
+#endif
+
+#ifdef _DEBUG
+#define DEB(x) x; fflush(stderr);
+#else
+#define DEB(x)
+#endif
+
+
+// --------------------------------------------------------------------------------------
+HttpRequest::HttpRequest() : HttpTransaction()
+, m_server_port(0)
+, m_is_ssl(false)
+, m_body_file(NULL)
+, m_form(NULL)
+{
+}
+
+
+// --------------------------------------------------------------------------------------
+HttpRequest::HttpRequest(const HttpRequest& src) : HttpTransaction(src)
+, m_method(src.m_method)
+, m_protocol(src.m_protocol)
+, m_req_uri(src.m_req_uri)
+, m_remote_addr(src.m_remote_addr)
+, m_remote_host(src.m_remote_host)
+, m_server_name(src.m_server_name)
+, m_server_port(src.m_server_port)
+, m_is_ssl(src.m_is_ssl)
+, m_attribute(src.m_attribute)
+, m_null(src.m_null)
+, m_body_file(src.m_body_file)
+, m_form(src.m_form)
+, m_cookies(src.m_cookies)
+, m_cookie(src.m_cookie)
+{
+}
+
+
+// --------------------------------------------------------------------------------------
+HttpRequest::~HttpRequest()
+{
+ m_body_file = std::auto_ptr<IFile>(NULL);
+ m_form = std::auto_ptr<HttpdForm>(NULL);
+/*
+ if (m_body_file)
+ {
+ delete m_body_file;
+ }
+ if (m_form)
+ {
+ delete m_form;
+ }
+*/
+}
+
+
+// --------------------------------------------------------------------------------------
+void HttpRequest::SetHttpMethod(const std::string& value)
+{
+ m_method = value;
+}
+
+
+const std::string& HttpRequest::HttpMethod() const
+{
+ return m_method;
+}
+
+
+
+// --------------------------------------------------------------------------------------
+void HttpRequest::SetHttpVersion(const std::string& value)
+{
+ m_protocol = value;
+}
+
+
+const std::string& HttpRequest::HttpVersion() const
+{
+ return m_protocol;
+}
+
+
+
+// --------------------------------------------------------------------------------------
+void HttpRequest::SetUri(const std::string& value)
+{
+ m_req_uri = Utility::rfc1738_decode(value);
+}
+
+
+const std::string& HttpRequest::Uri() const
+{
+ return m_req_uri;
+}
+
+
+
+// --------------------------------------------------------------------------------------
+void HttpRequest::SetRemoteAddr(const std::string& value)
+{
+ m_remote_addr = value;
+}
+
+
+const std::string& HttpRequest::RemoteAddr() const
+{
+ return m_remote_addr;
+}
+
+
+
+// --------------------------------------------------------------------------------------
+void HttpRequest::SetRemoteHost(const std::string& value)
+{
+ m_remote_host = value;
+}
+
+
+const std::string& HttpRequest::RemoteHost() const
+{
+ return m_remote_host;
+}
+
+
+
+// --------------------------------------------------------------------------------------
+void HttpRequest::SetServerName(const std::string& value)
+{
+ m_server_name = value;
+}
+
+
+const std::string& HttpRequest::ServerName() const
+{
+ return m_server_name;
+}
+
+
+
+// --------------------------------------------------------------------------------------
+void HttpRequest::SetServerPort(int value)
+{
+ m_server_port = value;
+}
+
+
+int HttpRequest::ServerPort() const
+{
+ return m_server_port;
+}
+
+
+
+// --------------------------------------------------------------------------------------
+void HttpRequest::SetIsSsl(bool value)
+{
+ m_is_ssl = value;
+}
+
+
+bool HttpRequest::IsSsl() const
+{
+ return m_is_ssl;
+}
+
+
+
+// --------------------------------------------------------------------------------------
+void HttpRequest::SetAttribute(const std::string& key, const std::string& value)
+{
+ m_attribute[Utility::ToLower(key)] = value;
+}
+
+
+void HttpRequest::SetAttribute(const std::string& key, long value)
+{
+ m_attribute[Utility::ToLower(key)] = Utility::l2string(value);
+}
+
+
+const std::string& HttpRequest::Attribute(const std::string& key) const
+{
+ std::map<std::string, std::string>::const_iterator it;
+ if ( (it = m_attribute.find(Utility::ToLower(key))) != m_attribute.end())
+ return it -> second;
+ return m_null;
+}
+
+
+// --------------------------------------------------------------------------------------
+const std::map<std::string, std::string>& HttpRequest::Attributes() const
+{
+ return m_attribute;
+}
+
+
+// --------------------------------------------------------------------------------------
+void HttpRequest::AddCookie(const std::string& str)
+{
+ m_cookies.add( str );
+ Parse pa(str, ";");
+ std::string lstr = pa.getword();
+ while (!lstr.empty())
+ {
+ Parse pa2(lstr, "=");
+ std::string name = pa2.getword();
+ m_cookie[name] = lstr;
+DEB(fprintf(stderr, " *** AddCookie '%s' = '%s'\n", name.c_str(), lstr.c_str());)
+ lstr = pa.getword();
+ }
+}
+
+
+// --------------------------------------------------------------------------------------
+void HttpRequest::InitBody( size_t sz )
+{
+ if (!m_body_file.get())
+ m_body_file = std::auto_ptr<IFile>(new MemFile);
+DEB( else
+ fprintf(stderr, "Body data file already opened\n");)
+}
+
+
+// --------------------------------------------------------------------------------------
+void HttpRequest::Write( const char *buf, size_t sz )
+{
+ if (m_body_file.get())
+ m_body_file -> fwrite(buf, 1, sz);
+DEB( else
+ fprintf(stderr, "Write: Body data file not open\n");)
+}
+
+
+// --------------------------------------------------------------------------------------
+void HttpRequest::CloseBody()
+{
+ if (m_body_file.get())
+ m_body_file -> fclose();
+DEB( else
+ fprintf(stderr, "CloseBody: File not open\n");)
+}
+
+
+// --------------------------------------------------------------------------------------
+void HttpRequest::ParseBody()
+{
+ std::map<std::string, std::string>::const_iterator it;
+ if ( (it = m_attribute.find("query_string")) != m_attribute.end())
+ {
+ std::string qs = it -> second;
+ m_form = std::auto_ptr<HttpdForm>(new HttpdForm( qs, qs.size() ));
+ }
+ else
+ if (m_body_file.get())
+ {
+ m_form = std::auto_ptr<HttpdForm>(new HttpdForm( m_body_file.get(), ContentType(), ContentLength() ));
+ }
+ else
+ {
+ // dummy
+ m_form = std::auto_ptr<HttpdForm>(new HttpdForm( "", 0 ));
+ }
+}
+
+
+// --------------------------------------------------------------------------------------
+const HttpdForm& HttpRequest::Form() const
+{
+ return *m_form;
+}
+
+
+// --------------------------------------------------------------------------------------
+const HttpdCookies& HttpRequest::Cookies() const
+{
+ return m_cookies;
+}
+
+
+// --------------------------------------------------------------------------------------
+void HttpRequest::Reset()
+{
+ HttpTransaction::Reset();
+ m_method = "";
+ m_protocol = "";
+ m_req_uri = "";
+ m_remote_addr = "";
+ m_remote_host = "";
+ m_server_name = "";
+ m_server_port = 0;
+ m_is_ssl = false;
+ while (!m_attribute.empty())
+ {
+ m_attribute.erase(m_attribute.begin());
+ }
+ m_body_file = std::auto_ptr<IFile>(NULL);
+ m_form = std::auto_ptr<HttpdForm>(NULL);
+/*
+ if (m_body_file)
+ {
+ delete m_body_file;
+ m_body_file = NULL;
+ }
+ if (m_form)
+ {
+ delete m_form;
+ m_form = NULL;
+ }
+*/
+ m_cookies.Reset();
+ while (!m_cookie.empty())
+ {
+ m_cookie.erase(m_cookie.begin());
+ }
+}
+
+
+#ifdef SOCKETS_NAMESPACE
+} // namespace SOCKETS_NAMESPACE {
+#endif
+
+
diff --git a/Sockets/HttpRequest.h b/Sockets/HttpRequest.h
new file mode 100644
index 0000000..38290e4
--- /dev/null
+++ b/Sockets/HttpRequest.h
@@ -0,0 +1,125 @@
+/**
+ ** \file HttpRequest.h
+ ** \date 2007-10-05
+ ** \author grymse@alhem.net
+**/
+/*
+Copyright (C) 2007 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.
+*/
+#ifndef _SOCKETS_HttpRequest_H
+#define _SOCKETS_HttpRequest_H
+
+#include "HttpTransaction.h"
+#include "HttpdCookies.h"
+#include <memory>
+#include "IFile.h"
+
+#ifdef SOCKETS_NAMESPACE
+namespace SOCKETS_NAMESPACE {
+#endif
+
+
+class HttpdForm;
+class IFile;
+
+class HttpRequest : public HttpTransaction
+{
+public:
+ HttpRequest();
+ HttpRequest(const HttpRequest& src);
+ ~HttpRequest();
+
+ /** Get, Post */
+ void SetHttpMethod(const std::string& value);
+ const std::string& HttpMethod() const;
+
+ /** HTTP/1.x */
+ void SetHttpVersion(const std::string& value);
+ const std::string& HttpVersion() const;
+
+ void SetUri(const std::string& value);
+ const std::string& Uri() const;
+
+ void SetRemoteAddr(const std::string& value);
+ const std::string& RemoteAddr() const;
+
+ void SetRemoteHost(const std::string& value);
+ const std::string& RemoteHost() const;
+
+ void SetServerName(const std::string& value);
+ const std::string& ServerName() const;
+
+ void SetServerPort(int value);
+ int ServerPort() const;
+
+ void SetIsSsl(bool value);
+ bool IsSsl() const;
+
+ /** Set / Read attribute value */
+ void SetAttribute(const std::string& key, const std::string& value);
+ void SetAttribute(const std::string& key, long value);
+ const std::string& Attribute(const std::string& key) const;
+
+ const std::map<std::string, std::string>& Attributes() const;
+
+ /** Cookies */
+ void AddCookie(const std::string& );
+ const std::map<std::string, std::string>& CookieMap() const { return m_cookie; }
+
+ /** Open file for body data */
+ void InitBody( size_t sz );
+
+ /** Write body data */
+ void Write( const char *buf, size_t sz );
+
+ /** No more writing */
+ void CloseBody();
+
+ void ParseBody();
+
+ const HttpdForm& Form() const;
+ const HttpdCookies& Cookies() const;
+
+ const IFile *BodyFile() const { return m_body_file.get(); }
+
+ void Reset();
+
+private:
+ std::string m_method;
+ std::string m_protocol;
+ std::string m_req_uri;
+ std::string m_remote_addr;
+ std::string m_remote_host;
+ std::string m_server_name;
+ int m_server_port;
+ bool m_is_ssl;
+ std::map<std::string, std::string> m_attribute;
+ std::string m_null;
+ mutable std::auto_ptr<IFile> m_body_file;
+ mutable std::auto_ptr<HttpdForm> m_form;
+ HttpdCookies m_cookies;
+ std::map<std::string, std::string> m_cookie;
+
+}; // end of class
+
+
+#ifdef SOCKETS_NAMESPACE
+} // namespace SOCKETS_NAMESPACE {
+#endif
+
+#endif // _SOCKETS_HttpRequest_H
+
diff --git a/Sockets/HttpResponse.cpp b/Sockets/HttpResponse.cpp
new file mode 100644
index 0000000..c312ee2
--- /dev/null
+++ b/Sockets/HttpResponse.cpp
@@ -0,0 +1,201 @@
+/**
+ ** \file HttpResponse.cpp
+ ** \date 2007-10-05
+ ** \author grymse@alhem.net
+**/
+/*
+Copyright (C) 2007 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 _MSC_VER
+#pragma warning(disable:4786)
+#endif
+#include <stdarg.h>
+#include <stdio.h>
+
+#include "HttpResponse.h"
+#include "HttpRequest.h"
+#include "MemFile.h"
+#include "File.h"
+#include "Parse.h"
+#include "Utility.h"
+
+#ifdef SOCKETS_NAMESPACE
+namespace SOCKETS_NAMESPACE {
+#endif
+
+#ifdef _DEBUG
+#define DEB(x) x; fflush(stderr);
+#else
+#define DEB(x)
+#endif
+
+
+// --------------------------------------------------------------------------------------
+HttpResponse::HttpResponse(const std::string& version) : HttpTransaction()
+, m_http_version( version )
+, m_http_status_code(0)
+, m_file( new MemFile )
+{
+}
+
+
+// --------------------------------------------------------------------------------------
+HttpResponse::~HttpResponse()
+{
+ delete m_file;
+}
+
+
+// --------------------------------------------------------------------------------------
+void HttpResponse::SetHttpVersion(const std::string& value)
+{
+ m_http_version = value;
+}
+
+
+// --------------------------------------------------------------------------------------
+const std::string& HttpResponse::HttpVersion() const
+{
+ return m_http_version;
+}
+
+
+
+// --------------------------------------------------------------------------------------
+void HttpResponse::SetHttpStatusCode(int value)
+{
+ m_http_status_code = value;
+}
+
+
+int HttpResponse::HttpStatusCode() const
+{
+ return m_http_status_code;
+}
+
+
+
+// --------------------------------------------------------------------------------------
+void HttpResponse::SetHttpStatusMsg(const std::string& value)
+{
+ m_http_status_msg = value;
+}
+
+
+const std::string& HttpResponse::HttpStatusMsg() const
+{
+ return m_http_status_msg;
+}
+
+
+// --------------------------------------------------------------------------------------
+void HttpResponse::SetCookie(const std::string& value)
+{
+ Parse pa(value, "=");
+ std::string name = pa.getword();
+ m_cookie[Utility::ToLower(name)] = value;
+DEB(fprintf(stderr, "HttpResponse::Set-Cookie<%s>: %s\n", name.c_str(), value.c_str());)
+}
+
+
+const std::string HttpResponse::Cookie(const std::string& name) const
+{
+ std::map<std::string, std::string>::const_iterator it = m_cookie.find(name);
+DEB(fprintf(stderr, "HttpResponse; get value of Cookie<%s>: ", name.c_str());)
+ if (it != m_cookie.end())
+ {
+DEB(fprintf(stderr, "%s\n", it -> second.c_str());)
+ return it -> second;
+ }
+DEB(fprintf(stderr, "\n");)
+ return "";
+}
+
+
+std::list<std::string> HttpResponse::CookieNames() const
+{
+ std::list<std::string> vec;
+ DEB(fprintf(stderr, "HttpResponse::CookieNames; ");)
+ for (std::map<std::string, std::string>::const_iterator it = m_cookie.begin(); it != m_cookie.end(); it++)
+ {
+ DEB(fprintf(stderr, " %s", it -> first.c_str());)
+ vec.push_back(it -> first);
+ }
+ DEB(fprintf(stderr, "\n");)
+ return vec;
+}
+
+
+
+// --------------------------------------------------------------------------------------
+void HttpResponse::Write( const std::string& str )
+{
+ Write( str.c_str(), str.size() );
+}
+
+
+// --------------------------------------------------------------------------------------
+void HttpResponse::Write( const char *buf, size_t sz )
+{
+ m_file -> fwrite( buf, 1, sz );
+}
+
+
+// --------------------------------------------------------------------------------------
+void HttpResponse::Writef( const char *format, ... )
+{
+ va_list ap;
+ va_start(ap, format);
+ char tmp[10000];
+ vsprintf(tmp, format, ap);
+ va_end(ap);
+ m_file -> fwrite( tmp, 1, strlen(tmp) );
+}
+
+
+// --------------------------------------------------------------------------------------
+void HttpResponse::SetFile( const std::string& path )
+{
+ delete m_file;
+ m_file = new File();
+ m_file -> fopen( path, "rb" );
+}
+
+
+// --------------------------------------------------------------------------------------
+void HttpResponse::Reset()
+{
+ HttpTransaction::Reset();
+ m_http_version = "";
+ m_http_status_code = 0;
+ m_http_status_msg = "";
+ while (!m_cookie.empty())
+ {
+ m_cookie.erase(m_cookie.begin());
+ }
+ if (m_file)
+ {
+ delete m_file;
+ m_file = new MemFile;
+ }
+}
+
+
+#ifdef SOCKETS_NAMESPACE
+} // namespace SOCKETS_NAMESPACE {
+#endif
+
diff --git a/Sockets/HttpResponse.h b/Sockets/HttpResponse.h
new file mode 100644
index 0000000..089ff1d
--- /dev/null
+++ b/Sockets/HttpResponse.h
@@ -0,0 +1,82 @@
+/**
+ ** \file HttpResponse.h
+ ** \date 2007-10-05
+ ** \author grymse@alhem.net
+**/
+/*
+Copyright (C) 2007 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.
+*/
+#ifndef _SOCKETS_HttpResponse_H
+#define _SOCKETS_HttpResponse_H
+
+#include "HttpTransaction.h"
+#include <list>
+
+#ifdef SOCKETS_NAMESPACE
+namespace SOCKETS_NAMESPACE {
+#endif
+
+
+class IFile;
+
+class HttpResponse : public HttpTransaction
+{
+public:
+ HttpResponse(const std::string& version = "HTTP/1.0");
+ ~HttpResponse();
+
+ /** HTTP/1.x */
+ void SetHttpVersion(const std::string& value);
+ const std::string& HttpVersion() const;
+
+ void SetHttpStatusCode(int value);
+ int HttpStatusCode() const;
+
+ void SetHttpStatusMsg(const std::string& value);
+ const std::string& HttpStatusMsg() const;
+
+ void SetCookie(const std::string& value);
+ const std::string Cookie(const std::string& name) const;
+ std::list<std::string> CookieNames() const;
+
+ void Write( const std::string& str );
+ void Write( const char *buf, size_t sz );
+ void Writef( const char *format, ... );
+
+ const IFile& GetFile() const { return *m_file; }
+
+ /** Replace memfile with file on disk, opened for read. */
+ void SetFile( const std::string& path );
+
+ void Reset();
+
+private:
+ std::string m_http_version;
+ int m_http_status_code;
+ std::string m_http_status_msg;
+ std::map<std::string, std::string> m_cookie;
+ IFile *m_file;
+
+}; // end of class
+
+
+#ifdef SOCKETS_NAMESPACE
+} // namespace SOCKETS_NAMESPACE {
+#endif
+
+#endif // _SOCKETS_HttpResponse_H
+
diff --git a/Sockets/HttpTransaction.cpp b/Sockets/HttpTransaction.cpp
new file mode 100644
index 0000000..8221d1f
--- /dev/null
+++ b/Sockets/HttpTransaction.cpp
@@ -0,0 +1,244 @@
+/**
+ ** \file HttpTransaction.cpp
+ ** \date 2007-10-05
+ ** \author grymse@alhem.net
+**/
+/*
+Copyright (C) 2007 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 _MSC_VER
+#pragma warning(disable:4786)
+#endif
+#include "HttpTransaction.h"
+#include "Utility.h"
+#include "Parse.h"
+
+#ifdef SOCKETS_NAMESPACE
+namespace SOCKETS_NAMESPACE {
+#endif
+
+
+// --------------------------------------------------------------------------------------
+HttpTransaction::HttpTransaction()
+{
+}
+
+
+// --------------------------------------------------------------------------------------
+HttpTransaction::~HttpTransaction()
+{
+}
+
+
+// --------------------------------------------------------------------------------------
+void HttpTransaction::SetHeader(const std::string& key, const std::string& value)
+{
+ m_header[Utility::ToLower(key)] = value;
+}
+
+
+void HttpTransaction::SetHeader(const std::string& key, long value)
+{
+ m_header[Utility::ToLower(key)] = Utility::l2string(value);
+}
+
+
+const std::string& HttpTransaction::Header(const std::string& key) const
+{
+ std::map<std::string, std::string>::const_iterator it;
+ if ((it = m_header.find(Utility::ToLower(key))) != m_header.end())
+ return it -> second;
+ return m_null;
+}
+
+
+
+// --------------------------------------------------------------------------------------
+void HttpTransaction::SetAccept(const std::string& value)
+{
+ SetHeader("accept", value);
+}
+
+
+const std::string& HttpTransaction::Accept() const
+{
+ return Header("accept");
+}
+
+
+
+// --------------------------------------------------------------------------------------
+void HttpTransaction::SetAcceptCharset(const std::string& value)
+{
+ SetHeader("accept-charset", value);
+}
+
+
+const std::string& HttpTransaction::AcceptCharset() const
+{
+ return Header("accept-charset");
+}
+
+
+
+// --------------------------------------------------------------------------------------
+void HttpTransaction::SetAcceptEncoding(const std::string& value)
+{
+ SetHeader("accept-encoding", value);
+}
+
+
+const std::string& HttpTransaction::AcceptEncoding() const
+{
+ return Header("accept-encoding");
+}
+
+
+
+// --------------------------------------------------------------------------------------
+void HttpTransaction::SetAcceptLanguage(const std::string& value)
+{
+ SetHeader("accept-language", value);
+}
+
+
+const std::string& HttpTransaction::AcceptLanguage() const
+{
+ return Header("accept-language");
+}
+
+
+
+// --------------------------------------------------------------------------------------
+void HttpTransaction::SetConnection(const std::string& value)
+{
+ SetHeader("connection", value);
+}
+
+
+const std::string& HttpTransaction::Connection() const
+{
+ return Header("connection");
+}
+
+
+
+// --------------------------------------------------------------------------------------
+void HttpTransaction::SetContentType(const std::string& value)
+{
+ SetHeader("content-type", value);
+}
+
+
+const std::string& HttpTransaction::ContentType() const
+{
+ return Header("content-type");
+}
+
+
+
+// --------------------------------------------------------------------------------------
+void HttpTransaction::SetContentLength(long value)
+{
+ SetHeader("content-length", value );
+}
+
+
+long HttpTransaction::ContentLength() const
+{
+ return atol(Header("content-length").c_str());
+}
+
+
+
+// --------------------------------------------------------------------------------------
+void HttpTransaction::SetHost(const std::string& value)
+{
+ SetHeader("host", value);
+}
+
+
+const std::string& HttpTransaction::Host() const
+{
+ return Header("host");
+}
+
+
+
+// --------------------------------------------------------------------------------------
+void HttpTransaction::SetPragma(const std::string& value)
+{
+ SetHeader("pragma", value);
+}
+
+
+const std::string& HttpTransaction::Pragma() const
+{
+ return Header("pragma");
+}
+
+
+
+// --------------------------------------------------------------------------------------
+void HttpTransaction::SetReferer(const std::string& value)
+{
+ SetHeader("referer", value);
+}
+
+
+const std::string& HttpTransaction::Referer() const
+{
+ return Header("referer");
+}
+
+
+
+// --------------------------------------------------------------------------------------
+void HttpTransaction::SetUserAgent(const std::string& value)
+{
+ SetHeader("user-agent", value);
+}
+
+
+const std::string& HttpTransaction::UserAgent() const
+{
+ return Header("user-agent");
+}
+
+
+// --------------------------------------------------------------------------------------
+const std::map<std::string, std::string>& HttpTransaction::Headers() const
+{
+ return m_header;
+}
+
+
+// --------------------------------------------------------------------------------------
+void HttpTransaction::Reset()
+{
+ while (!m_header.empty())
+ {
+ m_header.erase(m_header.begin());
+ }
+}
+
+
+#ifdef SOCKETS_NAMESPACE
+} // namespace SOCKETS_NAMESPACE {
+#endif
+
+
diff --git a/Sockets/HttpTransaction.h b/Sockets/HttpTransaction.h
new file mode 100644
index 0000000..a92fdda
--- /dev/null
+++ b/Sockets/HttpTransaction.h
@@ -0,0 +1,94 @@
+/**
+ ** \file HttpTransaction.h
+ ** \date 2007-10-05
+ ** \author grymse@alhem.net
+**/
+/*
+Copyright (C) 2007 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.
+*/
+#ifndef _SOCKETS_HttpTransaction_H
+#define _SOCKETS_HttpTransaction_H
+
+#include <string>
+#include <map>
+
+#ifdef SOCKETS_NAMESPACE
+namespace SOCKETS_NAMESPACE {
+#endif
+
+
+class HttpTransaction
+{
+public:
+ HttpTransaction();
+ virtual ~HttpTransaction();
+
+ /** Set / Read http header value */
+ void SetHeader(const std::string& key, const std::string& value);
+ void SetHeader(const std::string& key, long value);
+ const std::string& Header(const std::string& key) const;
+
+ void SetAccept(const std::string& value);
+ const std::string& Accept() const;
+
+ void SetAcceptCharset(const std::string& value);
+ const std::string& AcceptCharset() const;
+
+ void SetAcceptEncoding(const std::string& value);
+ const std::string& AcceptEncoding() const;
+
+ void SetAcceptLanguage(const std::string& value);
+ const std::string& AcceptLanguage() const;
+
+ void SetConnection(const std::string& value);
+ const std::string& Connection() const;
+
+ void SetContentType(const std::string& value);
+ const std::string& ContentType() const;
+
+ void SetContentLength(long value);
+ long ContentLength() const;
+
+ void SetHost(const std::string& value);
+ const std::string& Host() const;
+
+ void SetPragma(const std::string& value);
+ const std::string& Pragma() const;
+
+ void SetReferer(const std::string& value);
+ const std::string& Referer() const;
+
+ void SetUserAgent(const std::string& value);
+ const std::string& UserAgent() const;
+
+ const std::map<std::string, std::string>& Headers() const;
+
+ virtual void Reset();
+
+private:
+ std::map<std::string, std::string> m_header;
+ std::string m_null;
+
+}; // end of class
+
+
+#ifdef SOCKETS_NAMESPACE
+} // namespace SOCKETS_NAMESPACE {
+#endif
+
+#endif // _SOCKETS_HttpTransaction_H
+
diff --git a/Sockets/HttpdCookies.cpp b/Sockets/HttpdCookies.cpp
new file mode 100644
index 0000000..9662f0d
--- /dev/null
+++ b/Sockets/HttpdCookies.cpp
@@ -0,0 +1,270 @@
+/** \file HttpdCookies.cpp
+*/
+/*
+Copyright (C) 2003-2007 Anders Hedstrom
+
+This library is made available under the terms of the GNU GPL.
+
+If you would like to use this library in a closed-source application,
+a separate license agreement is available. For information about
+the closed-source license agreement for the C++ sockets library,
+please visit http://www.alhem.net/Sockets/license.html and/or
+email license@alhem.net.
+
+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 _MSC_VER
+#pragma warning(disable:4786)
+#endif
+#include "Parse.h"
+#include "Utility.h"
+#include "HTTPSocket.h"
+#include "HttpdCookies.h"
+
+#ifdef SOCKETS_NAMESPACE
+namespace SOCKETS_NAMESPACE {
+#endif
+
+#ifdef _DEBUG
+#define DEB(x) x; fflush(stderr);
+#else
+#define DEB(x)
+#endif
+
+
+HttpdCookies::HttpdCookies()
+{
+}
+
+HttpdCookies::HttpdCookies(const std::string& s)
+{
+ Parse *pa = new Parse(s,";");
+
+ std::string slask = pa -> getword();
+ while (slask.size())
+ {
+ Parse *pa2 = new Parse(slask,"=");
+ std::string name = pa2 -> getword();
+ std::string value = pa2 -> getword();
+ delete pa2;
+ m_cookies.push_back(std::pair<std::string, std::string>(name, value));
+ //
+ slask = pa -> getword();
+ }
+ delete pa;
+}
+
+void HttpdCookies::add(const std::string& s)
+{
+ Parse *pa = new Parse(s,";");
+DEB(fprintf(stderr, "Parse cookie: %s\n", s.c_str());)
+ std::string slask = pa -> getword();
+ while (slask.size())
+ {
+ Parse *pa2 = new Parse(slask,"=");
+ std::string name = pa2 -> getword();
+ std::string value = pa2 -> getword();
+ delete pa2;
+ m_cookies.push_back(std::pair<std::string, std::string>(name, value));
+ //
+ slask = pa -> getword();
+ }
+ delete pa;
+}
+
+HttpdCookies::~HttpdCookies()
+{
+}
+
+bool HttpdCookies::getvalue(const std::string& name,std::string& buffer) const
+{
+ for (cookie_v::const_iterator it = m_cookies.begin(); it != m_cookies.end(); it++)
+ {
+ const std::pair<std::string, std::string>& ref = *it;
+ if (!strcasecmp(ref.first.c_str(),name.c_str()))
+ {
+ buffer = ref.second;
+ return true;
+ }
+ }
+ buffer = "";
+ return false;
+}
+
+void HttpdCookies::replacevalue(const std::string& name,const std::string& value)
+{
+ for (cookie_v::iterator it = m_cookies.begin(); it != m_cookies.end(); it++)
+ {
+ std::pair<std::string, std::string>& ref = *it;
+ if (!strcasecmp(ref.first.c_str(),name.c_str()))
+ {
+ ref.second = value;
+ return;
+ }
+ }
+ m_cookies.push_back(std::pair<std::string, std::string>(name, value));
+
+}
+
+void HttpdCookies::replacevalue(const std::string& name,long l)
+{
+ replacevalue(name, Utility::l2string(l));
+}
+
+void HttpdCookies::replacevalue(const std::string& name,int i)
+{
+ replacevalue(name, Utility::l2string(i));
+}
+
+size_t HttpdCookies::getlength(const std::string& name) const
+{
+ for (cookie_v::const_iterator it = m_cookies.begin(); it != m_cookies.end(); it++)
+ {
+ const std::pair<std::string, std::string>& ref = *it;
+ if (!strcasecmp(ref.first.c_str(),name.c_str()))
+ {
+ return ref.second.size();
+ }
+ }
+ return 0;
+}
+
+void HttpdCookies::setcookie(HTTPSocket *sock, const std::string& domain, const std::string& path, const std::string& name, const std::string& value)
+{
+ char *str = new char[name.size() + value.size() + domain.size() + path.size() + 100];
+
+ // set-cookie response
+ if (domain.size())
+ {
+ sprintf(str, "%s=%s; domain=%s; path=%s; expires=%s",
+ name.c_str(), value.c_str(),
+ domain.c_str(),
+ path.c_str(),
+ expiredatetime().c_str());
+ }
+ else
+ {
+ sprintf(str, "%s=%s; path=%s; expires=%s",
+ name.c_str(), value.c_str(),
+ path.c_str(),
+ expiredatetime().c_str());
+ }
+ sock -> AddResponseHeader("Set-cookie", str);
+ delete[] str;
+
+ replacevalue(name, value);
+}
+
+void HttpdCookies::setcookie(HTTPSocket *sock, const std::string& domain, const std::string& path, const std::string& name, long value)
+{
+ char *str = new char[name.size() + domain.size() + path.size() + 100];
+ char dt[80];
+
+ // set-cookie response
+ if (domain.size())
+ {
+ sprintf(str, "%s=%ld; domain=%s; path=%s; expires=%s",
+ name.c_str(), value,
+ domain.c_str(),
+ path.c_str(),
+ expiredatetime().c_str());
+ }
+ else
+ {
+ sprintf(str, "%s=%ld; path=%s; expires=%s",
+ name.c_str(), value,
+ path.c_str(),
+ expiredatetime().c_str());
+ }
+ sock -> AddResponseHeader("Set-cookie", str);
+ delete[] str;
+
+ sprintf(dt, "%ld", value);
+ replacevalue(name, dt);
+}
+
+void HttpdCookies::setcookie(HTTPSocket *sock, const std::string& domain, const std::string& path, const std::string& name, int value)
+{
+ char *str = new char[name.size() + domain.size() + path.size() + 100];
+ char dt[80];
+
+ // set-cookie response
+ if (domain.size())
+ {
+ sprintf(str, "%s=%d; domain=%s; path=%s; expires=%s",
+ name.c_str(), value,
+ domain.c_str(),
+ path.c_str(),
+ expiredatetime().c_str());
+ }
+ else
+ {
+ sprintf(str, "%s=%d; path=%s; expires=%s",
+ name.c_str(), value,
+ path.c_str(),
+ expiredatetime().c_str());
+ }
+ sock -> AddResponseHeader("Set-cookie", str);
+ delete[] str;
+
+ sprintf(dt, "%d", value);
+ replacevalue(name, dt);
+}
+
+
+const std::string& HttpdCookies::expiredatetime() const
+{
+ time_t t = time(NULL);
+ struct tm tp;
+#ifdef _WIN32
+ memcpy(&tp, gmtime(&t), sizeof(tp));
+#else
+ gmtime_r(&t, &tp);
+#endif
+ const char *days[7] = {"Sunday", "Monday",
+ "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
+ const char *months[12] = {"Jan", "Feb", "Mar", "Apr", "May",
+ "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
+ char dt[100];
+
+ sprintf(dt, "%s, %02d-%s-%04d %02d:%02d:%02d GMT",
+ days[tp.tm_wday],
+ tp.tm_mday,
+ months[tp.tm_mon],
+ tp.tm_year + 1910,
+ tp.tm_hour,
+ tp.tm_min,
+ tp.tm_sec);
+ m_date = dt;
+ return m_date;
+}
+
+
+void HttpdCookies::Reset()
+{
+ while (!m_cookies.empty())
+ {
+ m_cookies.erase(m_cookies.begin());
+ }
+ m_date = "";
+}
+
+
+#ifdef SOCKETS_NAMESPACE
+}
+#endif
+
+
diff --git a/Sockets/HttpdCookies.h b/Sockets/HttpdCookies.h
new file mode 100644
index 0000000..79af17c
--- /dev/null
+++ b/Sockets/HttpdCookies.h
@@ -0,0 +1,89 @@
+/** \file HttpdCookies.h
+*/
+/*
+Copyright (C) 2003-2007 Anders Hedstrom
+
+This library is made available under the terms of the GNU GPL.
+
+If you would like to use this library in a closed-source application,
+a separate license agreement is available. For information about
+the closed-source license agreement for the C++ sockets library,
+please visit http://www.alhem.net/Sockets/license.html and/or
+email license@alhem.net.
+
+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.
+*/
+
+#ifndef _SOCKETS_HttpdCookies_H
+#define _SOCKETS_HttpdCookies_H
+
+#include "sockets-config.h"
+#include <list>
+#include <string>
+
+#ifdef SOCKETS_NAMESPACE
+namespace SOCKETS_NAMESPACE {
+#endif
+
+
+//! Store the cookies name/value pairs.
+
+
+
+//! Retrieve and manage cookies during a cgi call.
+class HTTPSocket;
+
+/** HTTP Cookie parse/container class.
+\sa HttpdSocket
+\sa HttpdForm
+\ingroup webserver */
+class HttpdCookies
+{
+ /** list of key/value structs. */
+ typedef std::list<std::pair<std::string, std::string> > cookie_v;
+
+public:
+ HttpdCookies();
+ HttpdCookies(const std::string& query_string);
+ ~HttpdCookies();
+
+ void add(const std::string& s);
+
+ bool getvalue(const std::string&,std::string&) const;
+ void replacevalue(const std::string& ,const std::string& );
+ void replacevalue(const std::string& ,long);
+ void replacevalue(const std::string& ,int);
+ size_t getlength(const std::string& ) const;
+ void setcookie(HTTPSocket *,const std::string& d,const std::string& p,const std::string& c,const std::string& v);
+ void setcookie(HTTPSocket *,const std::string& d,const std::string& p,const std::string& c,long v);
+ void setcookie(HTTPSocket *,const std::string& d,const std::string& p,const std::string& c,int v);
+ const std::string& expiredatetime() const;
+
+ cookie_v& GetHttpdCookies() { return m_cookies; }
+
+ void Reset();
+
+private:
+ cookie_v m_cookies;
+ mutable std::string m_date;
+};
+
+
+#ifdef SOCKETS_NAMESPACE
+}
+#endif
+
+#endif // _SOCKETS_HttpdCookies_H
+
diff --git a/Sockets/HttpdForm.cpp b/Sockets/HttpdForm.cpp
new file mode 100644
index 0000000..1b1f689
--- /dev/null
+++ b/Sockets/HttpdForm.cpp
@@ -0,0 +1,616 @@
+/** \file HttpdForm.cpp - read stdin, parse cgi input
+ **
+ ** Written: 1999-Feb-10 grymse@alhem.net
+ **/
+
+/*
+Copyright (C) 1999-2007 Anders Hedstrom
+
+This library is made available under the terms of the GNU GPL.
+
+If you would like to use this library in a closed-source application,
+a separate license agreement is available. For information about
+the closed-source license agreement for the C++ sockets library,
+please visit http://www.alhem.net/Sockets/license.html and/or
+email license@alhem.net.
+
+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 _MSC_VER
+#pragma warning(disable:4786)
+#endif
+#include "socket_include.h"
+#include "Parse.h"
+#include "IFile.h"
+#include "HttpdForm.h"
+
+#ifdef SOCKETS_NAMESPACE
+namespace SOCKETS_NAMESPACE {
+#endif
+
+#define TMPSIZE 10000
+
+
+HttpdForm::HttpdForm(IFile *infil, const std::string& content_type, size_t content_length) : raw(false)
+{
+ CGI *cgi = NULL;
+ size_t extra = 2;
+ char name[TMPSIZE];
+
+ m_current = m_cgi.end();
+ *name = 0;
+
+ if (content_type.size() >= 19 && content_type.substr(0, 19) == "multipart/form-data")
+ {
+ Parse pa(content_type,";=");
+ char *tempcmp = NULL;
+ size_t tc = 0;
+ size_t l = 0;
+ std::string str = pa.getword();
+ m_strBoundary = "";
+ while (str.size())
+ {
+ if (!strcmp(str.c_str(),"boundary"))
+ {
+ m_strBoundary = pa.getword();
+ l = m_strBoundary.size();
+ tempcmp = new char[l + extra];
+ }
+ //
+ str = pa.getword();
+ }
+ if (m_strBoundary.size())
+ {
+ std::string content_type;
+ std::string current_name;
+ std::string current_filename;
+ char *slask = new char[TMPSIZE];
+ infil -> fgets(slask, TMPSIZE);
+ while (!infil -> eof())
+ {
+ while (strlen(slask) && (slask[strlen(slask) - 1] == 13 || slask[strlen(slask) - 1] == 10))
+ {
+ slask[strlen(slask) - 1] = 0;
+ }
+ content_type = "";
+ current_name = "";
+ current_filename = "";
+ if ((strstr(slask,m_strBoundary.c_str()) || strstr(m_strBoundary.c_str(),slask)) && strcmp(slask, m_strBoundary.c_str()))
+ {
+ m_strBoundary = slask;
+ l = m_strBoundary.size();
+ delete[] tempcmp;
+ tempcmp = new char[l + extra];
+ }
+ if (!strcmp(slask, m_strBoundary.c_str()))
+ {
+ // Get headers until empty line
+ infil -> fgets(slask, TMPSIZE);
+ while (strlen(slask) && (slask[strlen(slask) - 1] == 13 || slask[strlen(slask) - 1] == 10))
+ {
+ slask[strlen(slask) - 1] = 0;
+ }
+ while (!infil -> eof() && *slask)
+ {
+ Parse pa(slask,";");
+ std::string h = pa.getword();
+ if (!strcasecmp(h.c_str(),"Content-type:"))
+ {
+ content_type = pa.getword();
+ }
+ else
+ if (!strcasecmp(h.c_str(),"Content-Disposition:"))
+ {
+ h = pa.getword();
+ if (!strcmp(h.c_str(),"form-data"))
+ {
+ pa.EnableQuote(true);
+ h = pa.getword();
+ while (h.size())
+ {
+ Parse pa2(slask,"=");
+ std::string name = pa2.getword();
+ std::string h = pa2.getrest();
+ if (!strcmp(name.c_str(),"name"))
+ {
+ if (h.size() && h[0] == '"')
+ {
+ current_name = h.substr(1, h.size() - 2);
+ }
+ else
+ {
+ current_name = h;
+ }
+ }
+ else
+ if (!strcmp(name.c_str(),"filename"))
+ {
+ if (h.size() && h[0] == '"')
+ {
+ current_filename = h.substr(1, h.size() - 2);
+ }
+ else
+ {
+ current_filename = h;
+ }
+ size_t x = 0;
+ for (size_t i = 0; i < current_filename.size(); i++)
+ {
+ if (current_filename[i] == '/' || current_filename[i] == '\\')
+ x = i + 1;
+ }
+ if (x)
+ {
+ current_filename = current_filename.substr(x);
+ }
+ }
+ h = pa.getword();
+ }
+ }
+ }
+ // get next header value
+ infil -> fgets(slask, TMPSIZE);
+ while (strlen(slask) && (slask[strlen(slask) - 1] == 13 || slask[strlen(slask) - 1] == 10))
+ {
+ slask[strlen(slask) - 1] = 0;
+ }
+ }
+ // Read content, save...?
+ if (!current_filename.size()) // not a file
+ {
+ std::string val;
+ infil -> fgets(slask, TMPSIZE);
+ while (!infil -> eof() && strncmp(slask,m_strBoundary.c_str(),m_strBoundary.size() ))
+ {
+ val += slask;
+ infil -> fgets(slask, TMPSIZE);
+ }
+ // remove trailing cr/linefeed
+ while (val.size() && (val[val.size() - 1] == 13 || val[val.size() - 1] == 10))
+ {
+ val = val.substr(0,val.size() - 1);
+ }
+ cgi = new CGI(current_name, val);
+ m_cgi.push_back(cgi);
+ }
+ else // current_filename.size() > 0
+ {
+ // read until m_strBoundary...
+ FILE *fil;
+ int out = 0;
+ char c;
+ char fn[2000]; // where post'd file will be saved
+#ifdef _WIN32
+ {
+ char tmp_path[2000];
+ ::GetTempPathA(2000, tmp_path);
+ if (tmp_path[strlen(tmp_path) - 1] != '\\')
+ {
+ strcat(tmp_path, "\\");
+ }
+ sprintf(fn,"%s%s",tmp_path,current_filename.c_str());
+ }
+#else
+ sprintf(fn,"/tmp/%s",current_filename.c_str());
+#endif
+ if ((fil = fopen(fn, "wb")) != NULL)
+ {
+ infil -> fread(&c,1,1);
+ while (!infil -> eof())
+ {
+ if (out)
+ {
+ fwrite(&tempcmp[tc],1,1,fil);
+ }
+ tempcmp[tc] = c;
+ tc++;
+ if (tc >= l + extra)
+ {
+ tc = 0;
+ out = 1;
+ }
+ if (tc)
+ {
+ if (!strncmp(tempcmp + tc + extra, m_strBoundary.c_str(), l - tc) &&
+ !strncmp(tempcmp, m_strBoundary.c_str() + l - tc, tc))
+ {
+ break;
+ }
+ }
+ else
+ {
+ if (!strncmp(tempcmp + extra, m_strBoundary.c_str(), l))
+ {
+ break;
+ }
+ }
+ infil -> fread(&c,1,1);
+ }
+ fclose(fil);
+
+ cgi = new CGI(current_name,fn,fn);
+ m_cgi.push_back(cgi);
+
+ strcpy(slask, m_strBoundary.c_str());
+ infil -> fgets(slask + strlen(slask), TMPSIZE); // next line
+ }
+ else
+ {
+ // couldn't open file
+ break;
+ }
+ }
+ }
+ else
+ {
+ // Probably '<m_strBoundary>--'
+ break;
+ }
+ } // while (!infil -> eof())
+ delete[] slask;
+ } // if (m_strBoundary)
+ if (tempcmp)
+ {
+ delete[] tempcmp;
+ }
+ }
+ else
+ if (strstr(content_type.c_str(), "x-www-form-urlencoded"))
+ {
+ bool got_name = false; // tnx to FatherNitwit
+ int i = 0;
+ int cl = (int)content_length;
+ char c,chigh,clow;
+ char *slask = new char[TMPSIZE];
+ m_current = m_cgi.end();
+
+ *name = 0;
+
+ infil -> fread(&c,1,1);
+ cl--;
+ while (cl >= 0 && !infil -> eof())
+ {
+ switch (c)
+ {
+ case '=': /* end of name */
+ slask[i] = 0;
+ i = 0;
+ strcpy(name,slask);
+ got_name = true;
+ break;
+ case '&': /* end of value */
+ slask[i] = 0;
+ i = 0;
+ if (got_name)
+ {
+ cgi = new CGI(name,slask);
+ got_name = false;
+ }
+ else
+ {
+ cgi = new CGI(slask, "");
+ }
+ m_cgi.push_back(cgi);
+ break;
+ case '+': /* space */
+ slask[i++] = ' ';
+ break;
+ case '%': /* hex value */
+ infil -> fread(&chigh,1,1);
+ cl--;
+ chigh -= 48 + (chigh > '9' ? 7 : 0) + (chigh >= 'a' ? 32 : 0);
+ infil -> fread(&clow,1,1);
+ cl--;
+ clow -= 48 + (clow > '9' ? 7 : 0) + (clow >= 'a' ? 32 : 0);
+ slask[i++] = (char)(chigh * 16 + clow);
+ break;
+ default: /* just another char */
+ slask[i++] = c;
+ break;
+ }
+ //
+ if (cl > 0)
+ {
+ infil -> fread(&c,1,1);
+ }
+ cl--;
+ }
+ slask[i] = 0;
+ i = 0;
+ if (got_name)
+ {
+ cgi = new CGI(name,slask);
+ }
+ else
+ {
+ cgi = new CGI(slask, "");
+ }
+ m_cgi.push_back(cgi);
+ delete[] slask;
+ }
+}
+
+
+// HttpdForm(buffer,l) -- request_method GET
+
+HttpdForm::HttpdForm(const std::string& buffer,size_t l) : raw(false)
+{
+ CGI *cgi = NULL;
+ char *slask = new char[TMPSIZE];
+ char *name = new char[TMPSIZE];
+ int i = 0;
+ char c,chigh,clow;
+ size_t ptr = 0;
+ bool got_name = false;
+
+ m_current = m_cgi.end();
+
+ *name = 0;
+
+ ptr = 0;
+ while (ptr < l)
+ {
+ c = buffer[ptr++];
+ switch (c)
+ {
+ case '=': /* end of name */
+ slask[i] = 0;
+ i = 0;
+ strcpy(name,slask);
+ got_name = true;
+ break;
+ case '&': /* end of value */
+ slask[i] = 0;
+ i = 0;
+ if (got_name)
+ {
+ cgi = new CGI(name,slask);
+ got_name = false;
+ }
+ else
+ {
+ cgi = new CGI(slask, "");
+ }
+ m_cgi.push_back(cgi);
+ break;
+ case '+': /* space */
+ slask[i++] = ' ';
+ break;
+ case '%': /* hex value */
+ chigh = buffer[ptr++];
+ chigh -= 48 + (chigh > '9' ? 7 : 0) + (chigh >= 'a' ? 32 : 0);
+ clow = buffer[ptr++];
+ clow -= 48 + (clow > '9' ? 7 : 0) + (clow >= 'a' ? 32 : 0);
+ slask[i++] = (char)(chigh * 16 + clow);
+ break;
+ default: /* just another char */
+ slask[i++] = c;
+ break;
+ }
+ }
+ slask[i] = 0;
+ i = 0;
+ if (got_name)
+ {
+ cgi = new CGI(name,slask);
+ }
+ else
+ {
+ cgi = new CGI(slask, "");
+ }
+ m_cgi.push_back(cgi);
+ delete[] slask;
+ delete[] name;
+}
+
+
+HttpdForm::~HttpdForm()
+{
+ CGI *cgi = NULL; //,*tmp;
+
+ for (cgi_v::iterator it = m_cgi.begin(); it != m_cgi.end(); it++)
+ {
+ cgi = *it;
+ delete cgi;
+ }
+}
+
+
+void HttpdForm::EnableRaw(bool b)
+{
+ raw = b;
+}
+
+
+void HttpdForm::strcpyval(std::string& v,const char *value) const
+{
+ v = "";
+ for (size_t i = 0; i < strlen(value); i++)
+ {
+ if (value[i] == '<')
+ {
+ v += "&lt;";
+ }
+ else
+ if (value[i] == '>')
+ {
+ v += "&gt;";
+ }
+ else
+ if (value[i] == '&')
+ {
+ v += "&amp;";
+ }
+ else
+ {
+ v += value[i];
+ }
+ }
+}
+
+
+bool HttpdForm::getfirst(std::string& n) const
+{
+ m_current = m_cgi.begin();
+ return getnext(n);
+}
+
+
+bool HttpdForm::getnext(std::string& n) const
+{
+ if (m_current != m_cgi.end() )
+ {
+ CGI *current = *m_current;
+ n = current -> name;
+ m_current++;
+ return true;
+ }
+ else
+ {
+ n = "";
+ }
+ return false;
+}
+
+
+bool HttpdForm::getfirst(std::string& n,std::string& v) const
+{
+ m_current = m_cgi.begin();
+ return getnext(n,v);
+}
+
+
+bool HttpdForm::getnext(std::string& n,std::string& v) const
+{
+ if (m_current != m_cgi.end() )
+ {
+ CGI *current = *m_current;
+ n = current -> name;
+ if (raw)
+ {
+ v = current -> value;
+ }
+ else
+ {
+ strcpyval(v,current -> value.c_str());
+ }
+ m_current++;
+ return true;
+ }
+ else
+ {
+ n = "";
+ }
+ return false;
+}
+
+
+int HttpdForm::getvalue(const std::string& n,std::string& v) const
+{
+ CGI *cgi = NULL;
+ int r = 0;
+
+ for (cgi_v::const_iterator it = m_cgi.begin(); it != m_cgi.end(); it++)
+ {
+ cgi = *it;
+ if (cgi -> name == n)
+ break;
+ cgi = NULL;
+ }
+ if (cgi)
+ {
+ if (raw)
+ {
+ v = cgi -> value;
+ }
+ else
+ {
+ strcpyval(v,cgi -> value.c_str());
+ }
+ r++;
+ }
+ else
+ {
+ v = "";
+ }
+
+ return r;
+}
+
+
+std::string HttpdForm::getvalue(const std::string& n) const
+{
+ for (cgi_v::const_iterator it = m_cgi.begin(); it != m_cgi.end(); it++)
+ {
+ CGI *cgi = *it;
+ if (cgi -> name == n)
+ {
+ return cgi -> value;
+ }
+ }
+ return "";
+}
+
+
+size_t HttpdForm::getlength(const std::string& n) const
+{
+ CGI *cgi = NULL;
+ size_t l;
+
+ for (cgi_v::const_iterator it = m_cgi.begin(); it != m_cgi.end(); it++)
+ {
+ cgi = *it;
+ if (cgi -> name == n)
+ break;
+ cgi = NULL;
+ }
+ l = cgi ? cgi -> value.size() : 0;
+ if (cgi && !raw)
+ {
+ for (size_t i = 0; i < cgi -> value.size(); i++)
+ {
+ switch (cgi -> value[i])
+ {
+ case '<': // &lt;
+ case '>': // &gt;
+ l += 4;
+ break;
+ case '&': // &amp;
+ l += 5;
+ break;
+ }
+ }
+ }
+ return l;
+}
+
+
+HttpdForm::cgi_v& HttpdForm::getbase()
+{
+ return m_cgi;
+}
+
+
+const std::string& HttpdForm::GetBoundary() const
+{
+ return m_strBoundary;
+}
+
+
+#ifdef SOCKETS_NAMESPACE
+}
+#endif
+
+
diff --git a/Sockets/HttpdForm.h b/Sockets/HttpdForm.h
new file mode 100644
index 0000000..962a753
--- /dev/null
+++ b/Sockets/HttpdForm.h
@@ -0,0 +1,118 @@
+/** \file HttpdForm.h - read stdin, parse cgi input
+ **
+ ** Written: 1999-Feb-10 grymse@alhem.net
+ **/
+
+/*
+Copyright (C) 1999-2007 Anders Hedstrom
+
+This library is made available under the terms of the GNU GPL.
+
+If you would like to use this library in a closed-source application,
+a separate license agreement is available. For information about
+the closed-source license agreement for the C++ sockets library,
+please visit http://www.alhem.net/Sockets/license.html and/or
+email license@alhem.net.
+
+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.
+*/
+
+#ifndef _SOCKETS_HttpdForm_H
+#define _SOCKETS_HttpdForm_H
+
+#include "sockets-config.h"
+#include <string>
+#include <list>
+
+#ifdef SOCKETS_NAMESPACE
+namespace SOCKETS_NAMESPACE {
+#endif
+
+
+class IFile;
+
+/** Parse/store a http query_string/form-data body.
+ \ingroup webserver */
+class HttpdForm
+{
+ /**
+ * Store the name/value pairs from a GET/POST operation.
+ * "name" does not have to be unique.
+ \ingroup webserver
+ */
+ struct CGI
+ {
+ CGI(const std::string& n,const std::string& v) : name(n),value(v) {}
+ CGI(const std::string& n,const std::string& v,const std::string& p) : name(n),value(v),path(p) {}
+ std::string name;
+ std::string value;
+ std::string path;
+ };
+ /** list of key/value pairs. */
+ typedef std::list<CGI *> cgi_v;
+
+public:
+ /**
+ * Default constructor (used in POST operations).
+ * Input is read from stdin. Number of characters to read
+ * can be found in the environment variable CONTENT_LENGTH.
+ */
+ HttpdForm(IFile *, const std::string& content_type, size_t content_length);
+ /**
+ * Another constructor (used in GET operations).
+ * Input is read from the environment variable QUERY_STRING.
+ * @param query_string The httpd server provided QUERY_STRING
+ * @param length Query string length.
+ */
+ HttpdForm(const std::string& query_string,size_t length);
+ ~HttpdForm();
+
+ void EnableRaw(bool);
+
+ /** Encode characters '<' '>' '&' as &lt; &gt; &amp; */
+ void strcpyval(std::string&,const char *) const;
+
+ /* get names */
+ bool getfirst(std::string& n) const;
+ bool getnext(std::string& n) const;
+
+ /* get names and values */
+ bool getfirst(std::string& n,std::string& v) const;
+ bool getnext(std::string& n,std::string& v) const;
+
+ /* get value */
+ int getvalue(const std::string& ,std::string& ) const;
+ std::string getvalue(const std::string& ) const;
+ size_t getlength(const std::string& ) const;
+ cgi_v& getbase();
+
+ const std::string& GetBoundary() const;
+
+private:
+ HttpdForm(const HttpdForm& ) {}
+ HttpdForm& operator=(const HttpdForm& ) { return *this; }
+ cgi_v m_cgi;
+ mutable cgi_v::const_iterator m_current;
+ std::string m_strBoundary;
+ bool raw;
+};
+
+
+#ifdef SOCKETS_NAMESPACE
+}
+#endif
+
+#endif // _SOCKETS_HttpdForm_H
+
diff --git a/Sockets/HttpdSocket.cpp b/Sockets/HttpdSocket.cpp
new file mode 100644
index 0000000..777dd07
--- /dev/null
+++ b/Sockets/HttpdSocket.cpp
@@ -0,0 +1,528 @@
+/** \file HttpdSocket.cpp
+*/
+/*
+Copyright (C) 2001-2007 Anders Hedstrom (grymse@alhem.net)
+
+This library is made available under the terms of the GNU GPL.
+
+If you would like to use this library in a closed-source application,
+a separate license agreement is available. For information about
+the closed-source license agreement for the C++ sockets library,
+please visit http://www.alhem.net/Sockets/license.html and/or
+email license@alhem.net.
+
+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 _MSC_VER
+#pragma warning(disable:4786)
+#endif
+#include "Utility.h"
+#include "HttpdCookies.h"
+#include "HttpdForm.h"
+#include "MemFile.h"
+#include "HttpdSocket.h"
+#include "Base64.h"
+
+
+#ifdef SOCKETS_NAMESPACE
+namespace SOCKETS_NAMESPACE {
+#endif
+
+#define TMPSIZE 10000
+
+
+// statics
+int HttpdSocket::m_request_count = 0;
+std::string HttpdSocket::m_start = "";
+
+
+HttpdSocket::HttpdSocket(ISocketHandler& h)
+:HTTPSocket(h)
+,m_content_length(0)
+,m_file(NULL)
+,m_received(0)
+,m_request_id(++m_request_count)
+,m_cookies(NULL)
+,m_form(NULL)
+{
+ m_http_date = datetime2httpdate(GetDate());
+ if (!m_start.size())
+ m_start = m_http_date;
+}
+
+
+HttpdSocket::~HttpdSocket()
+{
+ if (m_file)
+ {
+ delete m_file;
+ }
+ if (m_cookies)
+ delete m_cookies;
+ if (m_form)
+ delete m_form;
+}
+
+
+void HttpdSocket::OnFirst()
+{
+}
+
+
+void HttpdSocket::OnHeader(const std::string& key,const std::string& value)
+{
+ if (!strcasecmp(key.c_str(),"content-length"))
+ {
+ m_content_length = atoi(value.c_str());
+ m_content_length_str = value;
+ }
+ else
+ if (!strcasecmp(key.c_str(),"cookie"))
+ {
+ m_http_cookie = value;
+ }
+ else
+ if (!strcasecmp(key.c_str(),"content-type"))
+ {
+ m_content_type = value;
+ }
+ else
+ if (!strcasecmp(key.c_str(),"if-modified-since"))
+ {
+ m_if_modified_since = value;
+ }
+}
+
+
+void HttpdSocket::OnHeaderComplete()
+{
+ m_cookies = new HttpdCookies(m_http_cookie);
+
+ if (GetMethod() == "GET")
+ {
+ Utility::SetEnv("QUERY_STRING", GetQueryString());
+ }
+ Utility::SetEnv("REQUEST_METHOD", GetMethod());
+ Utility::SetEnv("HTTP_COOKIE", m_http_cookie);
+ Utility::SetEnv("CONTENT_TYPE", m_content_type);
+ Utility::SetEnv("CONTENT_LENGTH", m_content_length_str);
+/*
+#if (defined(SOLARIS8) || defined(SOLARIS))
+ {
+ char slask[TMPSIZE];
+ if (GetMethod() == "GET")
+ {
+ sprintf(slask,"QUERY_STRING=%s", GetQueryString().c_str());
+ putenv(slask);
+ }
+ sprintf(slask,"REQUEST_METHOD=%s", GetMethod().c_str());
+ putenv(slask);
+ sprintf(slask,"HTTP_COOKIE=%s", m_http_cookie.c_str());
+ putenv(slask);
+ sprintf(slask,"CONTENT_TYPE=%s", m_content_type.c_str());
+ putenv(slask);
+ sprintf(slask,"CONTENT_LENGTH=%s", m_content_length_str.c_str());
+ putenv(slask);
+ }
+#elif defined _WIN32
+ {
+ char slask[TMPSIZE];
+ if (GetMethod() == "GET")
+ {
+ sprintf(slask,"QUERY_STRING=%s", GetQueryString().c_str());
+ _putenv(slask);
+ }
+ sprintf(slask,"REQUEST_METHOD=%s", GetMethod().c_str());
+ _putenv(slask);
+ sprintf(slask,"HTTP_COOKIE=%s", m_http_cookie.c_str());
+ _putenv(slask);
+ sprintf(slask,"CONTENT_TYPE=%s", m_content_type.c_str());
+ _putenv(slask);
+ sprintf(slask,"CONTENT_LENGTH=%s", m_content_length_str.c_str());
+ _putenv(slask);
+ }
+#else
+ if (GetMethod() == "GET")
+ {
+ setenv("QUERY_STRING", GetQueryString().c_str(), 1);
+ }
+ setenv("REQUEST_METHOD", GetMethod().c_str(), 1);
+ setenv("HTTP_COOKIE", m_http_cookie.c_str(), 1);
+ setenv("CONTENT_TYPE", m_content_type.c_str(), 1);
+ setenv("CONTENT_LENGTH", m_content_length_str.c_str(), 1);
+#endif
+*/
+ if (GetMethod() == "POST")
+ {
+ m_file = new MemFile;
+ }
+ else
+ if (GetMethod() == "GET")
+ {
+ m_form = new HttpdForm(GetQueryString(), GetQueryString().size() );
+ AddResponseHeader("Date", datetime2httpdate(GetDate()) );
+ if (GetUri() == "/image")
+ {
+ std::string str64 =
+"iVBORw0KGgoAAAANSUhEUgAAAGAAAABeCAIAAABTioayAAAACXBIWXMAAABkAAAAZAAPlsXdAAAAUHRF"
+"WHRSYXcgcHJvZmlsZSB0eXBlIEFQUDEyAApnZW5lcmljIHByb2ZpbGUKICAgICAgMTUKNDQ3NTYzNmI3"
+"OTAwMDEwMDA0MDAwMDAwM2MwMDAwCg2F1B0AABb4SURBVHja7Xx7rGVXed/3WGs/zvPeuTPXMzbjcUpq"
+"HAwlpQlYoUlDaJsAiVuFFKSKGlUlKgXqIKJAKxfRR4IUZEpSt1FoQEK4oYQEErlSFAoKIEoo2BQasBmc"
+"2NjyYzxz5957Hnufvfd6fF//2Oecez2hvbXvmZkg3U9b556Zc85ea//291rf+n0bVRWO5P8udLUn8Jdd"
+"jgA6QI4AOkCOADpAjgA6QI4AOkCOADpAjgA6QI4AOkCOADpAjgA6QI4AOkCOADpAjgA6QMxVHHtfoUWx"
+"/dP+C5fvABGv4gwBAK9qPWg5NLbvrjIY302ujgapAmKrQQiqC3xAQQF0H1AIcyXSq4XeZdegfedfWs78"
+"jYKAAgDi3sVri4mqzH+D9DSTu+I2dyVNTEFRl34GUTUikiqotrgoAqqIAhBxqzj7ZocAighXWJUuI0Cq"
+"injJ+SMAIZKolkXlGrOzM61mjfckCoN+X9UjorU26wgb7HTSPAfDRlVVFQAR21NeOT26XAC1p10CpKoI"
+"iKTO+ckkFpO4vVX1Bh3kkKRsDCIBE4sIMRNx8FTPYgwQfJ1k4ZpT3W4nAQBVQaSF/1pcw+VE63JrEKiC"
+"KhChC83Fi6EYEyp2uzxYN4kFY6H1O63TIUQAiCIIEgK5Rke7zWhUE2a9AR+/JunmpIr7of/eA2hhWREA"
+"QUlBkGg8af7s7E4n75+6Lu/2iBkUAgJLhP2+RkSJsNU5ACUCQCAyxTQ88eS0rt1gSGdOD621Ik8zs8uH"
+"0eUCSDSqCDHGUD/2mCvLXpbWp051bEqqGoIAINHeVRHRJTMREQBEACQEUDa0vT07/2QZvbvxphO9vhGh"
+"1m0j0uVzSysGaOF6QASJQvD4yKN1UeiZ053eULzX4FsspB221RdVZWYARaTFaeYXjIgiqqpEag16jw9+"
+"e3daTH/gBevHjw1EoIXle0ODdJH/KQiCxiiPPOLrWX7taeh1o3ek8wQH26jUao1qa1ZPy6VbgNovtIAi"
+"gCoZK17l3GPNdFLf8H2djY1cRAlJUfHyhP+VAbQM6gsPAt/404uzypw509vYoMYhKCHOQxsAiAohaqtL"
+"OhdEUlAm8iEQEgAQIRHHGJGQkBSAjILyhXNaN9VzTuOgn6jOl9yXQ49WvJpXEFUhoAcf2t7apn7f5p04"
+"K9XVXkVcE4IXiSoRUEkFVYiAEZnZMltmoxFUKAYFJRWQiK4JwUfvoncxBnUNKMTBMUVKzj2OdSNzXC6P"
+"ka1mLbZMdkCQSbZ36q3z2Oma4yesAipwEI8iLkTD4GNEBGZGAEJSBUBQ0RAcqLBJBdRYC0gxKKqKqgrE"
+"4FUFgNAY7xFAOx0a79KTT4bvu4FVlYAUFRVgpXp0WID2W6gqIMXGyeOPN73ORm8QrcUQRFUUTNNEAIyt"
+"CxJ1PmQ2H093vvr1L0rUm5//N+5/4N7g4o/92Cs7/R6AiAIxi4AKsOGvf/3Ljz/x0F974S2nr7/RNd5a"
+"MqSj8e60JMPl9ddvSBRiVlBYaURbgQYtXI+qAhKce7JxLuMkGquq3K63GA0YEBFEFAEFNWx8rP7nV75w"
+"/sJjhs31z7n54vaWd3Vd10nWFQ1EBACERlERaHc0vrD1eNNEIkMkIURQNMY0Lj7+xGzz5CCxCMqwak/0"
+"7H3QUnf2LZR0VoWHHh7PytnO9nnnQ1XVohoVIqioMBMRGEuGbZbar977xe88+tDx9ecURVNUoZgUs6Is"
+"at80TfAxBAEFkdi40ASoqqqYTJomqoIoEhkyNs0StlRV9qlzJSGLCuy391XICjRoEbmEGR9/fFo10utC"
+"jFrOast2Vk2NtYRoGANCkiRRJDHm22fPfvozf3jL33w1BXvx4v+alOV4NPLONT5KlCyzPsQIEHxwXtTR"
+"aLQ7Gu0W5cw5EAVERKC800nyrndxNmucF8OrzxhXFcUQMLjGl1N7zanrTGKStEtkvJcYNAbxPjLbpglV"
+"1YjAuacufPx37+72jv3A837iqYtPlbNpPXNFWU3GRftNERGVEGII4l10LpSzejwqyqKqZm46KVUpeA1e"
+"isKRZe+SyaSZJ2ErlRVFMVBGGs2aAMYQ9fs9BXFumqdJmiaACCCzqlHwosY7+MQnP/LYYw/f9o/vEORi"
+"Ot0d7c6qZjQeVVWTcjYYWCIBTBHBeW1qrWqqinp3tF3WTROVrXGunhTNeBTKWTOMvU7emUz1+IYCoEgk"
+"4vnEDq1QzxKgpwcvbZfsFy5MQ+xaE0WAmLrdfpIgoRKRQlTVqm66nfSP/uj3P/PH/+0fvvbtJzb/Su0q"
+"1/jJZFqU1WRazGY7H/3ob/R6HcTYRmtCCh6cl0e+862imDnvkUwIDag4J87HPLfBu3FwwetzTiVsCXSV"
+"FaNnr0HL4AUAIhEVgzOjUeHzWgHyvEekWZIzY5TIDACwPjz2rW9/84MffN8PvvjlP/wjP1nVZac7dL6a"
+"TkvX+GJaFdPxZz/7iRi0hR0ASZkIFCXv9WMjdV0llpUzUGFkaxVJJECSmrKYNnXsJAKSrDBpfMYALW/O"
+"Eh1VJcCyno2mNRECYlPXzAwgT20V/W5qEzZs2NhmWrz/vf8u65x4zWtuZ+LhIMsTU1bFZFq4BqbT0ax0"
+"r339e05ec7KtRFtjIWhVO+T0Dz555wP/+3M+oAIoAmOa5mLTTGIkgqIsbd6/OCnO9NciRAa+agDtR2oJ"
+"kAiEIGTs5uZ6NZv1el0RiTEAQu0ccQYosQl33fUr933ts6dP3/C+975FoicGBNy+cFEizqpqVpZFUW2e"
+"uOn0mTMqjoiYGaJOZ42xPR9pMhkVxSwEQJQonsgAKJMR0PX19cY51amE1sL2V74PZW6HctLt8CISI6hQ"
+"nnYIaTjsqcJ4PBkOB8SAqDHGTqf7B7939+/8zm+dueH5SL3zF84bY0UFVMqicIJFUZSzWTkbAVVpKgRC"
+"BIjqnEuzCNhUs3I2mznvptNadcyUEHOWdkSE2cQYm8apoggorcA3rwagef4sKCJRBNgIBFVjDB8/fgxQ"
+"CAEMJIbP3n//r773jtPX3/zP3/Yh5swY7ORZFAEwH/iPb/va1/64CaFpmqZyvdycOG4tISEBooidVaFu"
+"uqpSOwhBogICIGrTVE3tQpQQfZqmo9F0Y70nogrKtLJgf9gwL6KiAKBN02xv"
+"T4hNJ82SxBpj806GKDFI1ci7/tVbtnYvvPvffHzj2BnndrMsURCM5D35RqtZ5byv66quK9FgjHZSawzPLYUQALwPABCjDIdZU9fW2DRLvZO6dgpS13WeZ7z4yQqT"
+"oVVokGqMAgAhhG6WFeV4wIOqruumMgZ63WN3vu9f3PeVz7/lbXfe/MJbGr+1udlhQiT1XqsZGwoiERRANEQBVQARjcQUQqjrWhQBE5B51EeEPM+tsSKSJmysb1wd"
+"Y0ySTGIZY0REYFxuq1w1gFpPqICiEqIqmMEgiYLdXj8EEY1BJOHhf/34f/7QB371lpfd+qpXvzHEyclret2cLRMAlI3vpmnVjGblyLtZiD4ExxiJmE1AVIkBAEV0"
+"NqtCmAFAjI0hCKJISMgxQpJam1gFcFUTfIyArFHEECEAtstjOETGeDgTUxBRERWJqpLnSZKse+/KcrZ+bC3GEIKcP7f9s6+7/Wd++o2G0RqXGCOxVrLGMIJToB//"
+"2z93zbUveN6NL/GvelOMs43jJ6whZgYAUcny1MUmRveyv/X31teve+73v3Bra5JkTlW982nWAQUEBERmTVKMIsv8bCVu+hmXXJel1dYxey/eh6ZxVdNs7QZrNpLE"
+"MhMxAmhTBwhU"
+"eDMa7wxz7PWstY21lCZp0zREtDtGHzuzWspxk3XTTm7zxB8/Dnlm5gOBzup44byrfVo3ShAsl3mPCCnG2FaL8jzzPjDJcDAb9oeJpcRaZiZCxMPuxj4zDbp0N1nb"
+"/wQRReRQz8qwneVZr9dLOQHQKN4FCUFOHM97nTSxIU1SQxo8MkdgyDLV2Yyk6fWU2Tvv+r0OmVxViAgBQwQmO1hT2fWMIc0MU56kxrkmhIgISnFnvBMa6XZ0Y70b"
+"JBplFQReDaPmUKt5XToiRRFNU5zNJiJxe3tre3u7KIrZrDQGT2z0+13D7NfWkk996g/f855f3tiwSWKtMYNB3uvRqVPZ5qY9ccKcvKY/HOS+abwPTdOUsxJQAcQa"
+"3Niwv/4f7rh48dGN4700tb1+59ix9SxNsyzPsk6ScJoRES+LVIvjsLKiehBgjJLmJkmwqmaIEKOv6zgcDpxzdTUeDrKsY/MMyun2nz14v4+QWOyvZ9NCT5ywk0kw"
+"hGxoPK0Iw/qgU85ciLC+1i3ruH7c7OzG8U519ptfrsvbmAFJCEkAu71OFLVJXnG0SSNRwPJyi2QlnKJnpkFPN+aWyoLzaSARcmIBxK2tHcvzPM1s42rF2Ol0vnX/"
+"N19766t+6idv/dR//7RNekUDX/of99766p/+qZff8uZ/+iZj+MMf/M3f/ujdx453Bv38Xe+648v33hsovPGNb3jlT7z0H/z9n/3zBx6KkhCa7dHk4siNp6WPMai4"
+"GIJGwKDqDBgFBMW2ugmEK/HShzAxvfStqnY6eaebpanpdPJer9fr9YbD9aIs3vGOn7/x+T/0mte99fOf+0JZlI88svvuf/3OW156653v/y+TIv7Ld75z89RzP/yh"
+"3woOzn774XvuuefMDX/17W+9vdM99f67fv+vv/jl7/iltzS1AyARcc4XRbmzuzuZTMbjcTWrfFNp8IbpcvAwnrGTXr7uV19cfGoMV43b2dkarh/LbYaIaUbfeejP"
+"LfX/2Vt/hTJ8/W1vfujBb9x371cfefTs2Qfvu/9bX5lOii//yeff8E/eXjf1ffc++KUvfvpFP/gSH8yXvvCZH/nRV9z1n37ZED7y8NlvfPMBm6RENktTiUmU2B5N"
+"MfFVsTHs4JxedVUBgqfxTlodVkREQiREJNVojbm4s9sd9keTOs+zaRUn4wJIHYhR7vWG1iaN4zw//tznvnQ8Lq6/nl70opcxnXzRi3/8Yx/78MMPPvCKV77uyScK"
+"Qnvt6RcgZszZbT//4sHGZhN8mvY6HZOmawIymkzzJCsnjliSNBVtAzoSLXahV+GEDluTnk8KkJCIkEANwfra4PxT57Z3dra2tqbj0ckzN06K3Y/d/WtPPPrgPb97"
+"dzGbfP+NNyMZSjqv+pk31BL/9IGvKcdXvOLnPvHxDzx57tGbnv+jtjvcOHndaLv4O3/39Zsbx//kc/cQpDF4xBgjxKigOuh1DSFIHAyGCsDMuIBowf68Ghr0NHSW"
+"irTIxwgBVQyhihiDKupjmfU2b//FX/vNf3/Hpz/1yTPPu3FtfXNtbfNNb373Rz5y529/+D3Dwdrtb/+3onLTTT/0kh9+5clrT2+evLZ201/4xbt+49d/6Rfe/HsR"
+"4bZ/9M5ud2392HUmSceTqTWapMY19Xh31xhuw8RyDojz97CKKPbMMuk9hgIAqMYoPkgIsWl81YSmcXXtnYshiCiUVd3t9fP+cGen9JK6Wpxz3W7X+4CIAJQwjXYv"
+"bhw/Nhx0ETUEr5CIRiZFgBDZC168uGWTZH1tfXd0AQkG/Rx02s3T3e1t72O/lyeGU8M2NVlms4ST1GRpkjCzQaI5P+SqFcwAgWhu98zExMzCDDEqqnbSrKkbonrQ"
+"607KWQOBGVRdmggzxhgQ0sFaDzE0bjwcDijgaLzT7XXSxDCR81HqsLm5joiI/sRG3/k6S7GqtWncrCz7vV7CbFqaDBG1eLTri7lSH1p/njVAC2p3a1ZKRERMFJmZ"
+"SIkQBFTVIJbTadaV4SDLsgBIWZ4TikosyzKx1DQ+SQkBkDyA63Sp3zej8e7aYNhN"
+"E05w0aQACJTHFBGYOuPR7nA4yJIENBIxMzK1xwKhuXmtAKFD7WoAzkMYEREJMzMLMRCRkIAAgaYWm2rqfTUc9m3CXqssyQhtt7NujPU+IAKSVFWVZMYIGAOdLDWG"
+"i2ICACFERMzzXCCyyqwoZ0XFDIYYRdkYYiIGNkgEhpEJiYB4CdBhI9khlxoICETErMzIBjkSMxsDqggiURRUEyYf/YXz59IsTfJMYrDWpmnqQ8VMbAwADQd9UW2a"
+"RlUUYlFOo8S6rtsklFgIzWh7R6MYTgAEoR2XmdtXNmwMG95nYiuRw0axNlwwozEkEcPcD0GMGgnaOiGAGkKTdmdlHZq65BJIh8Oh840PfmNjw9qWA62EqBrTNEGi"
+"siyzPGFIxuPx1JfqAwJYNqCKCIw0d3zMhtttJSbGuYXNHZAeXomeGUBLYmXLgSYijUogimCIhMgyBKMqGiOqIiIHRVBREUTpdVIVqYMGH3cu7HgNaZ5d3NoZrq05"
+"77zz62trTV1bm0gUDca5xte7KgKItuV3LsYlanUHmckaNoaMIUJc1IBWoz7PUoP2ZQZKBAJEIkjEzMaiVVElEdMypZhBZP4rEQGANElSRBWJIhrBVc1Ove28Q8RY"
+"haIsOnmH0bZfZgbLRkXaaN2GLGY2xliLxpJN2FhmA8xIzEiEuMo1x7MBaLHawAVNGZCQW1IUoFVVAYmgiqpxUVTbIxPh3O7AkgGANLeimpqEEKPIsDdUEcaIBubE"
+"TpnT69oYBQDMxIaY0RhjDVvDlts8A1ur3zfJw3qjFVDw2m4mImKGKGqYhUEtAMRFJQQAQaIsd0HaQonu8Z3mbHsCBInYEvD2XRsSIszTHWPYWDaGrGVrrbXGEhkm"
+"g0SkiwxoZezdZ5sHPb0w1IZ7JmajAmqVFFnm21OMqAARkVQgxgiw7Kab3+OFz8BFjaldNMByqbe0LGZmA3PjssYYYoPGEDMiQbtiRpx35V3ltdg+QwNEIAAlMECw"
+"10CICIEQiABAJUIUbQmtqm2nwZ6zWNxwwkV/Ai5Aovk6GA2zMcSGbELWmsQYYykxzKZNf9r4vr9n76omirAvnC3nxAjAtOCLIyoQARIgYowaYqQAIiBRFz0sqqD7"
+"am+I+5WH2hxiniAbg8aSNdZYtoYSIsNsGKmNa4gAArrSGHZ4H7QPo7YnDIgVgBRVERNgDG3sjRikLYSKgJCIggrqJYRLFNhvVy0TcZEQGottOmgNW0OGqTUuwqU5"
+"4cpb7lZCwZt7IiKAFhhSQEbECNrmJoTIJMIUAkdZCqqAzjf3W19Ne9pD86yPGYnJEBlLxpBhYwwZg0xA7TGvbyxnskom8Ep40stZKQEqoKIAKBChUSRAAgJgJolq"
+"WH2MIlFUVEi17VFddnjMzYsIFot0ZAZitMxsyDAaZDZIDLioJQAoos490F9OEmcr863QFhqNhIotNoREFEVjUCIlQVGKIhpx2ciyNLNFgbJ1K+16AucHATOaeWFj"
+"rzxGcwtfrfNZNUB7ffCgiECttpMitMUPYQJBiCRRMLaaIyAK836fvS2kdqt9bmI8RwqJgQiZieep6Tx3aksul6+xdJUatLyBrZlw6ywVkQCh7elSZozCoqqCCu0e"
+"P+3xefZyn7k/MqhtcjNXJ8KFNQG2vAVcphp7r6u8qMuB/b7esbYFF1RVZb5vFURk7nsIVEV0uaEluFeraAFibJkuS+Rg8bnuux8rYwNdIYBgX/chwDy2qMCCM4xz"
+"y4I2c95rFtzPN1jokS42BeZnJmrLKC0ul8XvXAmAYMlZaiGY3+TWHWP7CIa9msBfmALCHJe9dcjyKRZIl7SqfI+1hV+CUXu5oHvE8z2a9SJz0Zb7vO/JHrjvKRSL"
+"h5vsQ2+Oy+Wb+JUC6LuAden47Wf/HxO9Igb1Xca9ks8PWjjvxXV+F7X4f/12/sUrC9KVfsDSpcPtIbX/sq+aQf1FubpPoPoekKOHvB0gRwAdIEcAHSBHAB0gRwAd"
+"IEcAHSBHAB0gRwAdIEcAHSBHAB0gRwAdIP8HqHccFP4Rq4QAAAAASUVORK5CYII=";
+ Send64(str64, "image/png");
+ }
+ else
+ {
+ Exec();
+ }
+ Reset(); // prepare for next request
+ }
+ else
+ {
+ AddResponseHeader("Date", GetHttpDate());
+ AddResponseHeader("Connection", "close");
+ SetStatus("405");
+ SetStatusText("Method not allowed");
+ SendResponse();
+ }
+}
+
+
+void HttpdSocket::OnData(const char *p,size_t l)
+{
+ if (m_file)
+ {
+ m_file -> fwrite(p,1,l);
+ }
+ m_received += l;
+ if (m_received >= m_content_length && m_content_length)
+ {
+ // all done
+ if (m_file && !m_form)
+ {
+ m_form = new HttpdForm(m_file, m_content_type, m_content_length);
+ AddResponseHeader("Date", datetime2httpdate(GetDate()) );
+ if (GetUri() == "/image")
+ {
+ std::string str64 =
+"iVBORw0KGgoAAAANSUhEUgAAAGAAAABeCAIAAABTioayAAAACXBIWXMAAABkAAAAZAAPlsXdAAAAUHRF"
+"WHRSYXcgcHJvZmlsZSB0eXBlIEFQUDEyAApnZW5lcmljIHByb2ZpbGUKICAgICAgMTUKNDQ3NTYzNmI3"
+"OTAwMDEwMDA0MDAwMDAwM2MwMDAwCg2F1B0AABb4SURBVHja7Xx7rGVXed/3WGs/zvPeuTPXMzbjcUpq"
+"HAwlpQlYoUlDaJsAiVuFFKSKGlUlKgXqIKJAKxfRR4IUZEpSt1FoQEK4oYQEErlSFAoKIEoo2BQasBmc"
+"2NjyYzxz5957Hnufvfd6fF//2Oecez2hvbXvmZkg3U9b556Zc85ea//291rf+n0bVRWO5P8udLUn8Jdd"
+"jgA6QI4AOkCOADpAjgA6QI4AOkCOADpAjgA6QI4AOkCOADpAjgA6QI4AOkCOADpAjgA6QMxVHHtfoUWx"
+"/dP+C5fvABGv4gwBAK9qPWg5NLbvrjIY302ujgapAmKrQQiqC3xAQQF0H1AIcyXSq4XeZdegfedfWs78"
+"jYKAAgDi3sVri4mqzH+D9DSTu+I2dyVNTEFRl34GUTUikiqotrgoAqqIAhBxqzj7ZocAighXWJUuI0Cq"
+"injJ+SMAIZKolkXlGrOzM61mjfckCoN+X9UjorU26wgb7HTSPAfDRlVVFQAR21NeOT26XAC1p10CpKoI"
+"iKTO+ckkFpO4vVX1Bh3kkKRsDCIBE4sIMRNx8FTPYgwQfJ1k4ZpT3W4nAQBVQaSF/1pcw+VE63JrEKiC"
+"KhChC83Fi6EYEyp2uzxYN4kFY6H1O63TIUQAiCIIEgK5Rke7zWhUE2a9AR+/JunmpIr7of/eA2hhWREA"
+"QUlBkGg8af7s7E4n75+6Lu/2iBkUAgJLhP2+RkSJsNU5ACUCQCAyxTQ88eS0rt1gSGdOD621Ik8zs8uH"
+"0eUCSDSqCDHGUD/2mCvLXpbWp051bEqqGoIAINHeVRHRJTMREQBEACQEUDa0vT07/2QZvbvxphO9vhGh"
+"1m0j0uVzSysGaOF6QASJQvD4yKN1UeiZ053eULzX4FsspB221RdVZWYARaTFaeYXjIgiqqpEag16jw9+"
+"e3daTH/gBevHjw1EoIXle0ODdJH/KQiCxiiPPOLrWX7taeh1o3ek8wQH26jUao1qa1ZPy6VbgNovtIAi"
+"gCoZK17l3GPNdFLf8H2djY1cRAlJUfHyhP+VAbQM6gsPAt/404uzypw509vYoMYhKCHOQxsAiAohaqtL"
+"OhdEUlAm8iEQEgAQIRHHGJGQkBSAjILyhXNaN9VzTuOgn6jOl9yXQ49WvJpXEFUhoAcf2t7apn7f5p04"
+"K9XVXkVcE4IXiSoRUEkFVYiAEZnZMltmoxFUKAYFJRWQiK4JwUfvoncxBnUNKMTBMUVKzj2OdSNzXC6P"
+"ka1mLbZMdkCQSbZ36q3z2Oma4yesAipwEI8iLkTD4GNEBGZGAEJSBUBQ0RAcqLBJBdRYC0gxKKqKqgrE"
+"4FUFgNAY7xFAOx0a79KTT4bvu4FVlYAUFRVgpXp0WID2W6gqIMXGyeOPN73ORm8QrcUQRFUUTNNEAIyt"
+"CxJ1PmQ2H093vvr1L0rUm5//N+5/4N7g4o/92Cs7/R6AiAIxi4AKsOGvf/3Ljz/x0F974S2nr7/RNd5a"
+"MqSj8e60JMPl9ddvSBRiVlBYaURbgQYtXI+qAhKce7JxLuMkGquq3K63GA0YEBFEFAEFNWx8rP7nV75w"
+"/sJjhs31z7n54vaWd3Vd10nWFQ1EBACERlERaHc0vrD1eNNEIkMkIURQNMY0Lj7+xGzz5CCxCMqwak/0"
+"7H3QUnf2LZR0VoWHHh7PytnO9nnnQ1XVohoVIqioMBMRGEuGbZbar977xe88+tDx9ecURVNUoZgUs6Is"
+"at80TfAxBAEFkdi40ASoqqqYTJomqoIoEhkyNs0StlRV9qlzJSGLCuy391XICjRoEbmEGR9/fFo10utC"
+"jFrOast2Vk2NtYRoGANCkiRRJDHm22fPfvozf3jL33w1BXvx4v+alOV4NPLONT5KlCyzPsQIEHxwXtTR"
+"aLQ7Gu0W5cw5EAVERKC800nyrndxNmucF8OrzxhXFcUQMLjGl1N7zanrTGKStEtkvJcYNAbxPjLbpglV"
+"1YjAuacufPx37+72jv3A837iqYtPlbNpPXNFWU3GRftNERGVEGII4l10LpSzejwqyqKqZm46KVUpeA1e"
+"isKRZe+SyaSZJ2ErlRVFMVBGGs2aAMYQ9fs9BXFumqdJmiaACCCzqlHwosY7+MQnP/LYYw/f9o/vEORi"
+"Ot0d7c6qZjQeVVWTcjYYWCIBTBHBeW1qrWqqinp3tF3WTROVrXGunhTNeBTKWTOMvU7emUz1+IYCoEgk"
+"4vnEDq1QzxKgpwcvbZfsFy5MQ+xaE0WAmLrdfpIgoRKRQlTVqm66nfSP/uj3P/PH/+0fvvbtJzb/Su0q"
+"1/jJZFqU1WRazGY7H/3ob/R6HcTYRmtCCh6cl0e+862imDnvkUwIDag4J87HPLfBu3FwwetzTiVsCXSV"
+"FaNnr0HL4AUAIhEVgzOjUeHzWgHyvEekWZIzY5TIDACwPjz2rW9/84MffN8PvvjlP/wjP1nVZac7dL6a"
+"TkvX+GJaFdPxZz/7iRi0hR0ASZkIFCXv9WMjdV0llpUzUGFkaxVJJECSmrKYNnXsJAKSrDBpfMYALW/O"
+"Eh1VJcCyno2mNRECYlPXzAwgT20V/W5qEzZs2NhmWrz/vf8u65x4zWtuZ+LhIMsTU1bFZFq4BqbT0ax0"
+"r339e05ec7KtRFtjIWhVO+T0Dz555wP/+3M+oAIoAmOa5mLTTGIkgqIsbd6/OCnO9NciRAa+agDtR2oJ"
+"kAiEIGTs5uZ6NZv1el0RiTEAQu0ccQYosQl33fUr933ts6dP3/C+975FoicGBNy+cFEizqpqVpZFUW2e"
+"uOn0mTMqjoiYGaJOZ42xPR9pMhkVxSwEQJQonsgAKJMR0PX19cY51amE1sL2V74PZW6HctLt8CISI6hQ"
+"nnYIaTjsqcJ4PBkOB8SAqDHGTqf7B7939+/8zm+dueH5SL3zF84bY0UFVMqicIJFUZSzWTkbAVVpKgRC"
+"BIjqnEuzCNhUs3I2mznvptNadcyUEHOWdkSE2cQYm8apoggorcA3rwagef4sKCJRBNgIBFVjDB8/fgxQ"
+"CAEMJIbP3n//r773jtPX3/zP3/Yh5swY7ORZFAEwH/iPb/va1/64CaFpmqZyvdycOG4tISEBooidVaFu"
+"uqpSOwhBogICIGrTVE3tQpQQfZqmo9F0Y70nogrKtLJgf9gwL6KiAKBN02xv"
+"T4hNJ82SxBpj806GKDFI1ci7/tVbtnYvvPvffHzj2BnndrMsURCM5D35RqtZ5byv66quK9FgjHZSawzPLYUQALwPABCjDIdZU9fW2DRLvZO6dgpS13WeZ7z4yQqT"
+"oVVokGqMAgAhhG6WFeV4wIOqruumMgZ63WN3vu9f3PeVz7/lbXfe/MJbGr+1udlhQiT1XqsZGwoiERRANEQBVQARjcQUQqjrWhQBE5B51EeEPM+tsSKSJmysb1wd"
+"Y0ySTGIZY0REYFxuq1w1gFpPqICiEqIqmMEgiYLdXj8EEY1BJOHhf/34f/7QB371lpfd+qpXvzHEyclret2cLRMAlI3vpmnVjGblyLtZiD4ExxiJmE1AVIkBAEV0"
+"NqtCmAFAjI0hCKJISMgxQpJam1gFcFUTfIyArFHEECEAtstjOETGeDgTUxBRERWJqpLnSZKse+/KcrZ+bC3GEIKcP7f9s6+7/Wd++o2G0RqXGCOxVrLGMIJToB//"
+"2z93zbUveN6NL/GvelOMs43jJ6whZgYAUcny1MUmRveyv/X31teve+73v3Bra5JkTlW982nWAQUEBERmTVKMIsv8bCVu+hmXXJel1dYxey/eh6ZxVdNs7QZrNpLE"
+"MhMxAmhTBwhU"
+"eDMa7wxz7PWstY21lCZp0zREtDtGHzuzWspxk3XTTm7zxB8/Dnlm5gOBzup44byrfVo3ShAsl3mPCCnG2FaL8jzzPjDJcDAb9oeJpcRaZiZCxMPuxj4zDbp0N1nb"
+"/wQRReRQz8qwneVZr9dLOQHQKN4FCUFOHM97nTSxIU1SQxo8MkdgyDLV2Yyk6fWU2Tvv+r0OmVxViAgBQwQmO1hT2fWMIc0MU56kxrkmhIgISnFnvBMa6XZ0Y70b"
+"JBplFQReDaPmUKt5XToiRRFNU5zNJiJxe3tre3u7KIrZrDQGT2z0+13D7NfWkk996g/f855f3tiwSWKtMYNB3uvRqVPZ5qY9ccKcvKY/HOS+abwPTdOUsxJQAcQa"
+"3Niwv/4f7rh48dGN4700tb1+59ix9SxNsyzPsk6ScJoRES+LVIvjsLKiehBgjJLmJkmwqmaIEKOv6zgcDpxzdTUeDrKsY/MMyun2nz14v4+QWOyvZ9NCT5ywk0kw"
+"hGxoPK0Iw/qgU85ciLC+1i3ruH7c7OzG8U519ptfrsvbmAFJCEkAu71OFLVJXnG0SSNRwPJyi2QlnKJnpkFPN+aWyoLzaSARcmIBxK2tHcvzPM1s42rF2Ol0vnX/"
+"N19766t+6idv/dR//7RNekUDX/of99766p/+qZff8uZ/+iZj+MMf/M3f/ujdx453Bv38Xe+648v33hsovPGNb3jlT7z0H/z9n/3zBx6KkhCa7dHk4siNp6WPMai4"
+"GIJGwKDqDBgFBMW2ugmEK/HShzAxvfStqnY6eaebpanpdPJer9fr9YbD9aIs3vGOn7/x+T/0mte99fOf+0JZlI88svvuf/3OW156653v/y+TIv7Ld75z89RzP/yh"
+"3woOzn774XvuuefMDX/17W+9vdM99f67fv+vv/jl7/iltzS1AyARcc4XRbmzuzuZTMbjcTWrfFNp8IbpcvAwnrGTXr7uV19cfGoMV43b2dkarh/LbYaIaUbfeejP"
+"LfX/2Vt/hTJ8/W1vfujBb9x371cfefTs2Qfvu/9bX5lOii//yeff8E/eXjf1ffc++KUvfvpFP/gSH8yXvvCZH/nRV9z1n37ZED7y8NlvfPMBm6RENktTiUmU2B5N"
+"MfFVsTHs4JxedVUBgqfxTlodVkREQiREJNVojbm4s9sd9keTOs+zaRUn4wJIHYhR7vWG1iaN4zw//tznvnQ8Lq6/nl70opcxnXzRi3/8Yx/78MMPPvCKV77uyScK"
+"Qnvt6RcgZszZbT//4sHGZhN8mvY6HZOmawIymkzzJCsnjliSNBVtAzoSLXahV+GEDluTnk8KkJCIkEANwfra4PxT57Z3dra2tqbj0ckzN06K3Y/d/WtPPPrgPb97"
+"dzGbfP+NNyMZSjqv+pk31BL/9IGvKcdXvOLnPvHxDzx57tGbnv+jtjvcOHndaLv4O3/39Zsbx//kc/cQpDF4xBgjxKigOuh1DSFIHAyGCsDMuIBowf68Ghr0NHSW"
+"irTIxwgBVQyhihiDKupjmfU2b//FX/vNf3/Hpz/1yTPPu3FtfXNtbfNNb373Rz5y529/+D3Dwdrtb/+3onLTTT/0kh9+5clrT2+evLZ201/4xbt+49d/6Rfe/HsR"
+"4bZ/9M5ud2392HUmSceTqTWapMY19Xh31xhuw8RyDojz97CKKPbMMuk9hgIAqMYoPkgIsWl81YSmcXXtnYshiCiUVd3t9fP+cGen9JK6Wpxz3W7X+4CIAJQwjXYv"
+"bhw/Nhx0ETUEr5CIRiZFgBDZC168uGWTZH1tfXd0AQkG/Rx02s3T3e1t72O/lyeGU8M2NVlms4ST1GRpkjCzQaI5P+SqFcwAgWhu98zExMzCDDEqqnbSrKkbonrQ"
+"607KWQOBGVRdmggzxhgQ0sFaDzE0bjwcDijgaLzT7XXSxDCR81HqsLm5joiI/sRG3/k6S7GqtWncrCz7vV7CbFqaDBG1eLTri7lSH1p/njVAC2p3a1ZKRERMFJmZ"
+"SIkQBFTVIJbTadaV4SDLsgBIWZ4TikosyzKx1DQ+SQkBkDyA63Sp3zej8e7aYNhN"
+"E05w0aQACJTHFBGYOuPR7nA4yJIENBIxMzK1xwKhuXmtAKFD7WoAzkMYEREJMzMLMRCRkIAAgaYWm2rqfTUc9m3CXqssyQhtt7NujPU+IAKSVFWVZMYIGAOdLDWG"
+"i2ICACFERMzzXCCyyqwoZ0XFDIYYRdkYYiIGNkgEhpEJiYB4CdBhI9khlxoICETErMzIBjkSMxsDqggiURRUEyYf/YXz59IsTfJMYrDWpmnqQ8VMbAwADQd9UW2a"
+"RlUUYlFOo8S6rtsklFgIzWh7R6MYTgAEoR2XmdtXNmwMG95nYiuRw0axNlwwozEkEcPcD0GMGgnaOiGAGkKTdmdlHZq65BJIh8Oh840PfmNjw9qWA62EqBrTNEGi"
+"siyzPGFIxuPx1JfqAwJYNqCKCIw0d3zMhtttJSbGuYXNHZAeXomeGUBLYmXLgSYijUogimCIhMgyBKMqGiOqIiIHRVBREUTpdVIVqYMGH3cu7HgNaZ5d3NoZrq05"
+"77zz62trTV1bm0gUDca5xte7KgKItuV3LsYlanUHmckaNoaMIUJc1IBWoz7PUoP2ZQZKBAJEIkjEzMaiVVElEdMypZhBZP4rEQGANElSRBWJIhrBVc1Ove28Q8RY"
+"haIsOnmH0bZfZgbLRkXaaN2GLGY2xliLxpJN2FhmA8xIzEiEuMo1x7MBaLHawAVNGZCQW1IUoFVVAYmgiqpxUVTbIxPh3O7AkgGANLeimpqEEKPIsDdUEcaIBubE"
+"TpnT69oYBQDMxIaY0RhjDVvDlts8A1ur3zfJw3qjFVDw2m4mImKGKGqYhUEtAMRFJQQAQaIsd0HaQonu8Z3mbHsCBInYEvD2XRsSIszTHWPYWDaGrGVrrbXGEhkm"
+"g0SkiwxoZezdZ5sHPb0w1IZ7JmajAmqVFFnm21OMqAARkVQgxgiw7Kab3+OFz8BFjaldNMByqbe0LGZmA3PjssYYYoPGEDMiQbtiRpx35V3ltdg+QwNEIAAlMECw"
+"10CICIEQiABAJUIUbQmtqm2nwZ6zWNxwwkV/Ai5Aovk6GA2zMcSGbELWmsQYYykxzKZNf9r4vr9n76omirAvnC3nxAjAtOCLIyoQARIgYowaYqQAIiBRFz0sqqD7"
+"am+I+5WH2hxiniAbg8aSNdZYtoYSIsNsGKmNa4gAArrSGHZ4H7QPo7YnDIgVgBRVERNgDG3sjRikLYSKgJCIggrqJYRLFNhvVy0TcZEQGottOmgNW0OGqTUuwqU5"
+"4cpb7lZCwZt7IiKAFhhSQEbECNrmJoTIJMIUAkdZCqqAzjf3W19Ne9pD86yPGYnJEBlLxpBhYwwZg0xA7TGvbyxnskom8Ep40stZKQEqoKIAKBChUSRAAgJgJolq"
+"WH2MIlFUVEi17VFddnjMzYsIFot0ZAZitMxsyDAaZDZIDLioJQAoos490F9OEmcr863QFhqNhIotNoREFEVjUCIlQVGKIhpx2ciyNLNFgbJ1K+16AucHATOaeWFj"
+"rzxGcwtfrfNZNUB7ffCgiECttpMitMUPYQJBiCRRMLaaIyAK836fvS2kdqt9bmI8RwqJgQiZieep6Tx3aksul6+xdJUatLyBrZlw6ywVkQCh7elSZozCoqqCCu0e"
+"P+3xefZyn7k/MqhtcjNXJ8KFNQG2vAVcphp7r6u8qMuB/b7esbYFF1RVZb5vFURk7nsIVEV0uaEluFeraAFibJkuS+Rg8bnuux8rYwNdIYBgX/chwDy2qMCCM4xz"
+"y4I2c95rFtzPN1jokS42BeZnJmrLKC0ul8XvXAmAYMlZaiGY3+TWHWP7CIa9msBfmALCHJe9dcjyKRZIl7SqfI+1hV+CUXu5oHvE8z2a9SJz0Zb7vO/JHrjvKRSL"
+"h5vsQ2+Oy+Wb+JUC6LuAden47Wf/HxO9Igb1Xca9ks8PWjjvxXV+F7X4f/12/sUrC9KVfsDSpcPtIbX/sq+aQf1FubpPoPoekKOHvB0gRwAdIEcAHSBHAB0gRwAd"
+"IEcAHSBHAB0gRwAdIEcAHSBHAB0gRwAdIP8HqHccFP4Rq4QAAAAASUVORK5CYII=";
+ Send64(str64, "image/png");
+ }
+ else
+ {
+ Exec();
+ }
+ Reset(); // prepare for next request
+ }
+ }
+}
+
+
+void HttpdSocket::Send64(const std::string& str64, const std::string& type)
+{
+ Base64 bb;
+
+ if (!strcasecmp(m_start.c_str(), m_if_modified_since.c_str()))
+ {
+ SetStatus("304");
+ SetStatusText("Not Modified");
+ SendResponse();
+ }
+ else
+ {
+ size_t len = bb.decode_length(str64);
+ unsigned char *buf = new unsigned char[len];
+
+ SetStatus("200");
+ SetStatusText("OK");
+
+ AddResponseHeader("Content-length", Utility::l2string( (long)len) );
+ AddResponseHeader("Content-type", type );
+ AddResponseHeader("Last-modified", m_start);
+ SendResponse();
+
+ bb.decode(str64, buf, len);
+ SendBuf( (char *)buf, len);
+ delete[] buf;
+ }
+}
+
+
+std::string HttpdSocket::datetime2httpdate(const std::string& dt)
+{
+ struct tm tp;
+ time_t t;
+ const char *days[] = { "Sun","Mon","Tue","Wed","Thu","Fri","Sat" };
+ const char *months[] = { "Jan","Feb","Mar","Apr","May","Jun",
+ "Jul","Aug","Sep","Oct","Nov","Dec" };
+ int i;
+ char s[40];
+
+/* 1997-12-16 09:50:40 */
+
+ if (dt.size() == 19)
+ {
+ tp.tm_year = atoi(dt.substr(0,4).c_str()) - 1900;
+ i = atoi(dt.substr(5,2).c_str()) - 1;
+ tp.tm_mon = i >= 0 ? i : 0;
+ tp.tm_mday = atoi(dt.substr(8,2).c_str());
+ tp.tm_hour = atoi(dt.substr(11,2).c_str());
+ tp.tm_min = atoi(dt.substr(14,2).c_str());
+ tp.tm_sec = atoi(dt.substr(17,2).c_str());
+ tp.tm_wday = 0;
+ tp.tm_yday = 0;
+ tp.tm_isdst = 0;
+ t = mktime(&tp);
+ if (t == -1)
+ {
+ Handler().LogError(this, "datetime2httpdate", 0, "mktime() failed");
+ }
+
+ sprintf(s,"%s, %02d %s %d %02d:%02d:%02d GMT",
+ days[tp.tm_wday],
+ tp.tm_mday,
+ months[tp.tm_mon],
+ tp.tm_year + 1900,
+ tp.tm_hour,tp.tm_min,tp.tm_sec);
+ }
+ else
+ {
+ *s = 0;
+ }
+ return s;
+}
+
+
+std::string HttpdSocket::GetDate()
+{
+ time_t t = time(NULL);
+ struct tm tp;
+#ifdef _WIN32
+ memcpy(&tp, localtime(&t), sizeof(tp));
+#else
+ localtime_r(&t, &tp);
+#endif
+ char slask[40]; // yyyy-mm-dd hh:mm:ss
+ sprintf(slask,"%d-%02d-%02d %02d:%02d:%02d",
+ tp.tm_year + 1900,
+ tp.tm_mon + 1,
+ tp.tm_mday,
+ tp.tm_hour,tp.tm_min,tp.tm_sec);
+ return slask;
+}
+
+
+void HttpdSocket::Reset()
+{
+ HTTPSocket::Reset();
+ m_content_length = 0;
+ if (m_file)
+ {
+ delete m_file;
+ m_file = NULL;
+ }
+ m_received = 0;
+ m_request_id = ++m_request_count;
+ if (m_cookies)
+ delete m_cookies;
+ m_cookies = NULL;
+ if (m_form)
+ delete m_form;
+ m_form = NULL;
+}
+
+
+const std::string& HttpdSocket::GetHttpDate() const
+{
+ return m_http_date;
+}
+
+
+HttpdCookies *HttpdSocket::GetCookies()
+{
+ return m_cookies;
+}
+
+
+const HttpdForm *HttpdSocket::GetForm() const
+{
+ return m_form;
+}
+
+
+
+#ifdef SOCKETS_NAMESPACE
+}
+#endif
+
+
diff --git a/Sockets/HttpdSocket.h b/Sockets/HttpdSocket.h
new file mode 100644
index 0000000..c4d10f5
--- /dev/null
+++ b/Sockets/HttpdSocket.h
@@ -0,0 +1,106 @@
+/** \file HttpdSocket.h
+*/
+/*
+Copyright (C) 2001-2007 Anders Hedstrom (grymse@alhem.net)
+
+This library is made available under the terms of the GNU GPL.
+
+If you would like to use this library in a closed-source application,
+a separate license agreement is available. For information about
+the closed-source license agreement for the C++ sockets library,
+please visit http://www.alhem.net/Sockets/license.html and/or
+email license@alhem.net.
+
+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.
+*/
+#ifndef _SOCKETS_HttpdSocket_H
+#define _SOCKETS_HttpdSocket_H
+
+#include "sockets-config.h"
+#include "HTTPSocket.h"
+#include "ISocketHandler.h"
+
+#ifdef SOCKETS_NAMESPACE
+namespace SOCKETS_NAMESPACE {
+#endif
+
+
+class HttpdCookies;
+class HttpdForm;
+class IFile;
+
+/** \defgroup webserver Webserver framework */
+/** Web server socket framework.
+ \ingroup webserver */
+class HttpdSocket : public HTTPSocket
+{
+public:
+ HttpdSocket(ISocketHandler& );
+ ~HttpdSocket();
+
+ void OnFirst();
+ void OnHeader(const std::string& key,const std::string& value);
+ void OnHeaderComplete();
+ void OnData(const char *,size_t);
+
+ /** This method needs to be implemented with logic to produce
+ a response to an incoming request. */
+ virtual void Exec() = 0;
+ /** Get current date in http rfc format. */
+ const std::string& GetHttpDate() const;
+ /** Get pointer to cookie class. */
+ HttpdCookies *GetCookies();
+ /** Get pointer to query string/form data class. */
+ const HttpdForm *GetForm() const;
+
+ size_t ContentLength() const { return m_content_length; }
+ const IFile *Body() const { return m_file; }
+ int RequestId() const { return m_request_id; }
+
+protected:
+ HttpdSocket(const HttpdSocket& s) : HTTPSocket(s) {}
+ /** Decode and send a base64-encoded string.
+ \param str64 Base64-encoded string
+ \param type Mime type of content (content-type header) */
+ void Send64(const std::string& str64, const std::string& type);
+ std::string datetime2httpdate(const std::string& dt);
+ std::string GetDate();
+ void Reset();
+ // headers
+ std::string m_http_cookie;
+ std::string m_content_type;
+ std::string m_content_length_str;
+ std::string m_if_modified_since;
+
+private:
+ HttpdSocket& operator=(const HttpdSocket& s) { return *this; }
+static int m_request_count;
+static std::string m_start;
+ size_t m_content_length;
+ IFile *m_file;
+ size_t m_received;
+ int m_request_id;
+ std::string m_http_date;
+ HttpdCookies *m_cookies;
+ HttpdForm *m_form;
+};
+
+
+#ifdef SOCKETS_NAMESPACE
+}
+#endif
+
+#endif // _SOCKETS_HttpdSocket_H
+
diff --git a/Sockets/IBase.h b/Sockets/IBase.h
new file mode 100644
index 0000000..93bfdf9
--- /dev/null
+++ b/Sockets/IBase.h
@@ -0,0 +1,44 @@
+/**
+ ** \file
+ ** \date 2007-06-05
+ ** \author grymse@alhem.net
+**/
+/*
+Copyright (C) 2007 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.
+*/
+#ifndef _SOCKETS_IBase_H
+#define _SOCKETS_IBase_H
+
+#ifdef SOCKETS_NAMESPACE
+namespace SOCKETS_NAMESPACE {
+#endif
+
+
+class IBase
+{
+public:
+ virtual ~IBase() {}
+
+};
+
+
+#ifdef SOCKETS_NAMESPACE
+} // namespace SOCKETS_NAMESPACE {
+#endif
+
+#endif // _SOCKETS_IBase_H
+
diff --git a/Sockets/IEventHandler.h b/Sockets/IEventHandler.h
new file mode 100644
index 0000000..fcbc432
--- /dev/null
+++ b/Sockets/IEventHandler.h
@@ -0,0 +1,75 @@
+/** \file IEventHandler.h
+ ** \date 2005-12-07
+ ** \author grymse@alhem.net
+**/
+/*
+Copyright (C) 2005,2007 Anders Hedstrom
+
+This library is made available under the terms of the GNU GPL.
+
+If you would like to use this library in a closed-source application,
+a separate license agreement is available. For information about
+the closed-source license agreement for the C++ sockets library,
+please visit http://www.alhem.net/Sockets/license.html and/or
+email license@alhem.net.
+
+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.
+*/
+#ifndef _SOCKETS_IEventHandler_H
+#define _SOCKETS_IEventHandler_H
+
+#include "sockets-config.h"
+
+#ifdef SOCKETS_NAMESPACE
+namespace SOCKETS_NAMESPACE {
+#endif
+
+
+class IEventOwner;
+
+/** Timer event handler pure virtual base class.
+ \ingroup timer */
+class IEventHandler
+{
+public:
+ virtual ~IEventHandler() {}
+
+ /** Return time left until next event.
+ \param tv Time struct that will be filled by method
+ \return true if time is set for next event */
+ virtual bool GetTimeUntilNextEvent(struct timeval *) = 0;
+ /** Will fire events whose time has come. */
+ virtual void CheckEvents() = 0;
+ /** Schedule event for an owner.
+ \param from Event owner
+ \param sec Seconds until event
+ \param usec Microseconds until event */
+ virtual long AddEvent(IEventOwner *,long sec,long usec) = 0;
+ /** Clear all events for a specific owner. */
+ virtual void ClearEvents(IEventOwner *) = 0;
+ /** Remove one specific event for an event owner. */
+ virtual void RemoveEvent(IEventOwner *,long) = 0;
+
+};
+
+
+
+
+#ifdef SOCKETS_NAMESPACE
+}
+#endif
+
+#endif // _SOCKETS_IEventHandler_H
+
diff --git a/Sockets/IEventOwner.cpp b/Sockets/IEventOwner.cpp
new file mode 100644
index 0000000..6c73551
--- /dev/null
+++ b/Sockets/IEventOwner.cpp
@@ -0,0 +1,79 @@
+/** \file IEventOwner.cpp
+ ** \date 2005-12-07
+ ** \author grymse@alhem.net
+**/
+/*
+Copyright (C) 2005,2007 Anders Hedstrom
+
+This library is made available under the terms of the GNU GPL.
+
+If you would like to use this library in a closed-source application,
+a separate license agreement is available. For information about
+the closed-source license agreement for the C++ sockets library,
+please visit http://www.alhem.net/Sockets/license.html and/or
+email license@alhem.net.
+
+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.
+*/
+#include "IEventOwner.h"
+
+
+#ifdef SOCKETS_NAMESPACE
+namespace SOCKETS_NAMESPACE {
+#endif
+
+
+IEventOwner::IEventOwner(IEventHandler& h) : m_event_handler(h), m_handler_invalid(false)
+{
+}
+
+
+IEventOwner::~IEventOwner()
+{
+ if (!m_handler_invalid)
+ {
+ m_event_handler.ClearEvents(this);
+ }
+}
+
+
+IEventHandler& IEventOwner::EventHandler()
+{
+ return m_event_handler;
+}
+
+
+long IEventOwner::AddEvent(long sec,long usec)
+{
+ return m_event_handler.AddEvent(this, sec, usec);
+}
+
+
+void IEventOwner::ClearEvents()
+{
+ m_event_handler.ClearEvents(this);
+}
+
+
+void IEventOwner::RemoveEvent(long eid)
+{
+ m_event_handler.RemoveEvent(this, eid);
+}
+
+
+#ifdef SOCKETS_NAMESPACE
+}
+#endif
+
diff --git a/Sockets/IEventOwner.h b/Sockets/IEventOwner.h
new file mode 100644
index 0000000..f3fc1cd
--- /dev/null
+++ b/Sockets/IEventOwner.h
@@ -0,0 +1,77 @@
+/** \file IEventOwner.h
+ ** \date 2005-12-07
+ ** \author grymse@alhem.net
+**/
+/*
+Copyright (C) 2005,2007 Anders Hedstrom
+
+This library is made available under the terms of the GNU GPL.
+
+If you would like to use this library in a closed-source application,
+a separate license agreement is available. For information about
+the closed-source license agreement for the C++ sockets library,
+please visit http://www.alhem.net/Sockets/license.html and/or
+email license@alhem.net.
+
+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.
+*/
+#ifndef _SOCKETS_IEventOwner_H
+#define _SOCKETS_IEventOwner_H
+
+#include "sockets-config.h"
+#include "IEventHandler.h"
+
+#ifdef SOCKETS_NAMESPACE
+namespace SOCKETS_NAMESPACE {
+#endif
+
+
+/** Any class that wants to use timer events inherits this.
+ \ingroup timer */
+class IEventOwner
+{
+public:
+ IEventOwner(IEventHandler& h);
+ virtual ~IEventOwner();
+
+ /** Schedule event.
+ \param sec Seconds until event
+ \param usec Microseconds until event
+ \return Event ID */
+ long AddEvent(long sec,long usec);
+ /** Clear all events scheduled by this owner. */
+ void ClearEvents();
+ /** Remove one event scheduled by this owner.
+ \param eid Event ID to remove */
+ void RemoveEvent(long eid);
+ /** Event callback will fire when time is up. */
+ virtual void OnEvent(int) = 0;
+
+ IEventHandler& EventHandler();
+ void SetHandlerInvalid(bool x = true) { m_handler_invalid = x; }
+
+private:
+ IEventHandler& m_event_handler;
+ bool m_handler_invalid;
+};
+
+
+
+#ifdef SOCKETS_NAMESPACE
+}
+#endif
+
+#endif // _SOCKETS_IEventOwner_H
+
diff --git a/Sockets/IFile.h b/Sockets/IFile.h
new file mode 100644
index 0000000..aecc50f
--- /dev/null
+++ b/Sockets/IFile.h
@@ -0,0 +1,71 @@
+/** \file IFile.h
+ ** \date 2005-04-25
+ ** \author grymse@alhem.net
+**/
+/*
+Copyright (C) 2004-2007 Anders Hedstrom
+
+This library is made available under the terms of the GNU GPL.
+
+If you would like to use this library in a closed-source application,
+a separate license agreement is available. For information about
+the closed-source license agreement for the C++ sockets library,
+please visit http://www.alhem.net/Sockets/license.html and/or
+email license@alhem.net.
+
+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.
+*/
+#ifndef _SOCKETS_IFile_H
+#define _SOCKETS_IFile_H
+
+#include "sockets-config.h"
+#include <string>
+
+#ifdef SOCKETS_NAMESPACE
+namespace SOCKETS_NAMESPACE {
+#endif
+
+/** \defgroup file File handling */
+/** Pure virtual file I/O interface.
+ \ingroup file */
+class IFile
+{
+public:
+ virtual ~IFile() {}
+
+ virtual bool fopen(const std::string&, const std::string&) = 0;
+ virtual void fclose() = 0;
+
+ virtual size_t fread(char *, size_t, size_t) const = 0;
+ virtual size_t fwrite(const char *, size_t, size_t) = 0;
+
+ virtual char *fgets(char *, int) const = 0;
+ virtual void fprintf(const char *format, ...) = 0;
+
+ virtual off_t size() const = 0;
+ virtual bool eof() const = 0;
+
+ virtual void reset_read() const = 0;
+ virtual void reset_write() = 0;
+
+};
+
+
+#ifdef SOCKETS_NAMESPACE
+}
+#endif
+
+#endif // _SOCKETS_IFile_H
+
diff --git a/Sockets/IHttpServer.h b/Sockets/IHttpServer.h
new file mode 100644
index 0000000..34e34c3
--- /dev/null
+++ b/Sockets/IHttpServer.h
@@ -0,0 +1,56 @@
+/**
+ ** \file IHttpServer.h
+ ** \date 2007-10-05
+ ** \author grymse@alhem.net
+**/
+/*
+Copyright (C) 2007 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.
+*/
+#ifndef _SOCKETS_IHttpServer_H
+#define _SOCKETS_IHttpServer_H
+
+#ifdef SOCKETS_NAMESPACE
+namespace SOCKETS_NAMESPACE {
+#endif
+
+
+class HttpRequest;
+class HttpResponse;
+
+class IHttpServer
+{
+public:
+ virtual ~IHttpServer() {}
+
+ /** Complete request has been received and parsed. Send response
+ using the Respond() method. */
+ virtual void OnExec(const HttpRequest& req) = 0;
+
+ /** Send response. */
+ virtual void Respond(const HttpResponse& res) = 0;
+
+};
+
+
+
+
+#ifdef SOCKETS_NAMESPACE
+} // namespace SOCKETS_NAMESPACE {
+#endif
+
+#endif // _SOCKETS_IHttpServer_H
+
diff --git a/Sockets/ISocketHandler.h b/Sockets/ISocketHandler.h
new file mode 100644
index 0000000..e32463e
--- /dev/null
+++ b/Sockets/ISocketHandler.h
@@ -0,0 +1,233 @@
+/** \file ISocketHandler.h
+ ** \date 2004-02-13
+ ** \author grymse@alhem.net
+**/
+/*
+Copyright (C) 2004-2007 Anders Hedstrom
+
+This library is made available under the terms of the GNU GPL.
+
+If you would like to use this library in a closed-source application,
+a separate license agreement is available. For information about
+the closed-source license agreement for the C++ sockets library,
+please visit http://www.alhem.net/Sockets/license.html and/or
+email license@alhem.net.
+
+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.
+*/
+#ifndef _SOCKETS_ISocketHandler_H
+#define _SOCKETS_ISocketHandler_H
+#include "sockets-config.h"
+
+#include <map>
+#include <list>
+
+#include "socket_include.h"
+#include "Socket.h"
+#include "StdLog.h"
+
+#ifdef SOCKETS_NAMESPACE
+namespace SOCKETS_NAMESPACE {
+#endif
+
+typedef enum {
+ LIST_CALLONCONNECT = 0,
+#ifdef ENABLE_DETACH
+ LIST_DETACH,
+#endif
+ LIST_TIMEOUT,
+ LIST_RETRY,
+ LIST_CLOSE
+} list_t;
+
+class SocketAddress;
+class Mutex;
+
+
+/** Socket container class, event generator.
+ \ingroup basic */
+class ISocketHandler
+{
+ friend class Socket;
+
+public:
+ /** Connection pool class for internal use by the ISocketHandler.
+ \ingroup internal */
+#ifdef ENABLE_POOL
+ class PoolSocket : public Socket
+ {
+ public:
+ PoolSocket(ISocketHandler& h,Socket *src) : Socket(h) {
+ CopyConnection( src );
+ SetIsClient();
+ }
+
+ void OnRead() {
+ Handler().LogError(this, "OnRead", 0, "data on hibernating socket", LOG_LEVEL_FATAL);
+ SetCloseAndDelete();
+ }
+ void OnOptions(int,int,int,SOCKET) {}
+
+ };
+#endif
+
+public:
+ virtual ~ISocketHandler() {}
+
+ /** Get mutex reference for threadsafe operations. */
+ virtual Mutex& GetMutex() const = 0;
+
+ /** Register StdLog object for error callback.
+ \param log Pointer to log class */
+ virtual void RegStdLog(StdLog *log) = 0;
+
+ /** Log error to log class for print out / storage. */
+ virtual void LogError(Socket *p,const std::string& user_text,int err,const std::string& sys_err,loglevel_t t = LOG_LEVEL_WARNING) = 0;
+
+ // -------------------------------------------------------------------------
+ // Socket stuff
+ // -------------------------------------------------------------------------
+ /** Add socket instance to socket map. Removal is always automatic. */
+ virtual void Add(Socket *) = 0;
+private:
+ /** Remove socket from socket map, used by Socket class. */
+ virtual void Remove(Socket *) = 0;
+public:
+ /** Get status of read/write/exception file descriptor set for a socket. */
+ virtual void Get(SOCKET s,bool& r,bool& w,bool& e) = 0;
+ /** Set read/write/exception file descriptor sets (fd_set). */
+ virtual void Set(SOCKET s,bool bRead,bool bWrite,bool bException = true) = 0;
+
+ /** Wait for events, generate callbacks. */
+ virtual int Select(long sec,long usec) = 0;
+ /** This method will not return until an event has been detected. */
+ virtual int Select() = 0;
+ /** Wait for events, generate callbacks. */
+ virtual int Select(struct timeval *tsel) = 0;
+
+ /** Check that a socket really is handled by this socket handler. */
+ virtual bool Valid(Socket *) = 0;
+ /** Return number of sockets handled by this handler. */
+ virtual size_t GetCount() = 0;
+
+ /** Override and return false to deny all incoming connections.
+ \param p ListenSocket class pointer (use GetPort to identify which one) */
+ virtual bool OkToAccept(Socket *p) = 0;
+
+ /** Called by Socket when a socket changes state. */
+ virtual void AddList(SOCKET s,list_t which_one,bool add) = 0;
+
+ // -------------------------------------------------------------------------
+ // Connection pool
+ // -------------------------------------------------------------------------
+#ifdef ENABLE_POOL
+ /** Find available open connection (used by connection pool). */
+ virtual ISocketHandler::PoolSocket *FindConnection(int type,const std::string& protocol,SocketAddress&) = 0;
+ /** Enable connection pool (by default disabled). */
+ virtual void EnablePool(bool = true) = 0;
+ /** Check pool status.
+ \return true if connection pool is enabled */
+ virtual bool PoolEnabled() = 0;
+#endif // ENABLE_POOL
+
+ // -------------------------------------------------------------------------
+ // Socks4
+ // -------------------------------------------------------------------------
+#ifdef ENABLE_SOCKS4
+ /** Set socks4 server ip that all new tcp sockets should use. */
+ virtual void SetSocks4Host(ipaddr_t) = 0;
+ /** Set socks4 server hostname that all new tcp sockets should use. */
+ virtual void SetSocks4Host(const std::string& ) = 0;
+ /** Set socks4 server port number that all new tcp sockets should use. */
+ virtual void SetSocks4Port(port_t) = 0;
+ /** Set optional socks4 userid. */
+ virtual void SetSocks4Userid(const std::string& ) = 0;
+ /** If connection to socks4 server fails, immediately try direct connection to final host. */
+ virtual void SetSocks4TryDirect(bool = true) = 0;
+ /** Get socks4 server ip.
+ \return socks4 server ip */
+ virtual ipaddr_t GetSocks4Host() = 0;
+ /** Get socks4 port number.
+ \return socks4 port number */
+ virtual port_t GetSocks4Port() = 0;
+ /** Get socks4 userid (optional).
+ \return socks4 userid */
+ virtual const std::string& GetSocks4Userid() = 0;
+ /** Check status of socks4 try direct flag.
+ \return true if direct connection should be tried if connection to socks4 server fails */
+ virtual bool Socks4TryDirect() = 0;
+#endif // ENABLE_SOCKS4
+
+ // -------------------------------------------------------------------------
+ // DNS resolve server
+ // -------------------------------------------------------------------------
+#ifdef ENABLE_RESOLVER
+ /** Enable asynchronous DNS.
+ \param port Listen port of asynchronous dns server */
+ virtual void EnableResolver(port_t = 16667) = 0;
+ /** Check resolver status.
+ \return true if resolver is enabled */
+ virtual bool ResolverEnabled() = 0;
+ /** Queue a dns request.
+ \param host Hostname to be resolved
+ \param port Port number will be echoed in Socket::OnResolved callback */
+ virtual int Resolve(Socket *,const std::string& host,port_t port) = 0;
+#ifdef ENABLE_IPV6
+ virtual int Resolve6(Socket *,const std::string& host,port_t port) = 0;
+#endif
+ /** Do a reverse dns lookup. */
+ virtual int Resolve(Socket *,ipaddr_t a) = 0;
+#ifdef ENABLE_IPV6
+ virtual int Resolve(Socket *,in6_addr& a) = 0;
+#endif
+ /** Get listen port of asynchronous dns server. */
+ virtual port_t GetResolverPort() = 0;
+ /** Resolver thread ready for queries. */
+ virtual bool ResolverReady() = 0;
+ /** Returns true if socket waiting for a resolve event. */
+ virtual bool Resolving(Socket *) = 0;
+#endif // ENABLE_RESOLVER
+
+#ifdef ENABLE_TRIGGERS
+ /** Fetch unique trigger id. */
+ virtual int TriggerID(Socket *src) = 0;
+ /** Subscribe socket to trigger id. */
+ virtual bool Subscribe(int id, Socket *dst) = 0;
+ /** Unsubscribe socket from trigger id. */
+ virtual bool Unsubscribe(int id, Socket *dst) = 0;
+ /** Execute OnTrigger for subscribed sockets.
+ \param id Trigger ID
+ \param data Data passed from source to destination
+ \param erase Empty trigger id source and destination maps if 'true',
+ Leave them in place if 'false' - if a trigger should be called many times */
+ virtual void Trigger(int id, Socket::TriggerData& data, bool erase = true) = 0;
+#endif // ENABLE_TRIGGERS
+
+#ifdef ENABLE_DETACH
+ /** Indicates that the handler runs under SocketThread. */
+ virtual void SetSlave(bool x = true) = 0;
+ /** Indicates that the handler runs under SocketThread. */
+ virtual bool IsSlave() = 0;
+#endif // ENABLE_DETACH
+
+};
+
+
+#ifdef SOCKETS_NAMESPACE
+}
+#endif
+
+#endif // _SOCKETS_ISocketHandler_H
+
diff --git a/Sockets/Ipv4Address.cpp b/Sockets/Ipv4Address.cpp
new file mode 100644
index 0000000..58f25e5
--- /dev/null
+++ b/Sockets/Ipv4Address.cpp
@@ -0,0 +1,214 @@
+/**
+ ** \file Ipv4Address.cpp
+ ** \date 2006-09-21
+ ** \author grymse@alhem.net
+**/
+/*
+Copyright (C) 2007 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.
+*/
+#include "Ipv4Address.h"
+#include "Utility.h"
+#include "Parse.h"
+#ifndef _WIN32
+#include <netdb.h>
+#endif
+
+
+#ifdef SOCKETS_NAMESPACE
+namespace SOCKETS_NAMESPACE {
+#endif
+
+
+
+Ipv4Address::Ipv4Address(port_t port) : m_valid(true)
+{
+ memset(&m_addr, 0, sizeof(m_addr));
+ m_addr.sin_family = AF_INET;
+ m_addr.sin_port = htons( port );
+}
+
+
+Ipv4Address::Ipv4Address(ipaddr_t a,port_t port) : m_valid(true)
+{
+ memset(&m_addr, 0, sizeof(m_addr));
+ m_addr.sin_family = AF_INET;
+ m_addr.sin_port = htons( port );
+ memcpy(&m_addr.sin_addr, &a, sizeof(struct in_addr));
+}
+
+
+Ipv4Address::Ipv4Address(struct in_addr& a,port_t port) : m_valid(true)
+{
+ memset(&m_addr, 0, sizeof(m_addr));
+ m_addr.sin_family = AF_INET;
+ m_addr.sin_port = htons( port );
+ m_addr.sin_addr = a;
+}
+
+
+Ipv4Address::Ipv4Address(const std::string& host,port_t port) : m_valid(false)
+{
+ memset(&m_addr, 0, sizeof(m_addr));
+ m_addr.sin_family = AF_INET;
+ m_addr.sin_port = htons( port );
+ {
+ ipaddr_t a;
+ if (Utility::u2ip(host, a))
+ {
+ memcpy(&m_addr.sin_addr, &a, sizeof(struct in_addr));
+ m_valid = true;
+ }
+ }
+}
+
+
+Ipv4Address::Ipv4Address(struct sockaddr_in& sa)
+{
+ m_addr = sa;
+ m_valid = sa.sin_family == AF_INET;
+}
+
+
+Ipv4Address::~Ipv4Address()
+{
+}
+
+
+Ipv4Address::operator struct sockaddr *()
+{
+ return (struct sockaddr *)&m_addr;
+}
+
+
+Ipv4Address::operator socklen_t()
+{
+ return sizeof(struct sockaddr_in);
+}
+
+
+void Ipv4Address::SetPort(port_t port)
+{
+ m_addr.sin_port = htons( port );
+}
+
+
+port_t Ipv4Address::GetPort()
+{
+ return ntohs( m_addr.sin_port );
+}
+
+
+bool Ipv4Address::Resolve(const std::string& hostname,struct in_addr& a)
+{
+ struct sockaddr_in sa;
+ memset(&a, 0, sizeof(a));
+ if (Utility::isipv4(hostname))
+ {
+ if (!Utility::u2ip(hostname, sa, AI_NUMERICHOST))
+ return false;
+ a = sa.sin_addr;
+ return true;
+ }
+ if (!Utility::u2ip(hostname, sa))
+ return false;
+ a = sa.sin_addr;
+ return true;
+}
+
+
+bool Ipv4Address::Reverse(struct in_addr& a,std::string& name)
+{
+ struct sockaddr_in sa;
+ memset(&sa, 0, sizeof(sa));
+ sa.sin_family = AF_INET;
+ sa.sin_addr = a;
+ return Utility::reverse((struct sockaddr *)&sa, sizeof(sa), name);
+}
+
+
+std::string Ipv4Address::Convert(bool include_port)
+{
+ if (include_port)
+ return Convert(m_addr.sin_addr) + ":" + Utility::l2string(GetPort());
+ return Convert(m_addr.sin_addr);
+}
+
+
+std::string Ipv4Address::Convert(struct in_addr& a)
+{
+ struct sockaddr_in sa;
+ memset(&sa, 0, sizeof(sa));
+ sa.sin_family = AF_INET;
+ sa.sin_addr = a;
+ std::string name;
+ Utility::reverse((struct sockaddr *)&sa, sizeof(sa), name, NI_NUMERICHOST);
+ return name;
+}
+
+
+void Ipv4Address::SetAddress(struct sockaddr *sa)
+{
+ memcpy(&m_addr, sa, sizeof(struct sockaddr_in));
+}
+
+
+int Ipv4Address::GetFamily()
+{
+ return m_addr.sin_family;
+}
+
+
+bool Ipv4Address::IsValid()
+{
+ return m_valid;
+}
+
+
+bool Ipv4Address::operator==(SocketAddress& a)
+{
+ if (a.GetFamily() != GetFamily())
+ return false;
+ if ((socklen_t)a != sizeof(m_addr))
+ return false;
+ struct sockaddr *sa = a;
+ struct sockaddr_in *p = (struct sockaddr_in *)sa;
+ if (p -> sin_port != m_addr.sin_port)
+ return false;
+ if (memcmp(&p -> sin_addr, &m_addr.sin_addr, 4))
+ return false;
+ return true;
+}
+
+
+std::auto_ptr<SocketAddress> Ipv4Address::GetCopy()
+{
+ return std::auto_ptr<SocketAddress>(new Ipv4Address(m_addr));
+}
+
+
+std::string Ipv4Address::Reverse()
+{
+ std::string tmp;
+ Reverse(m_addr.sin_addr, tmp);
+ return tmp;
+}
+
+
+#ifdef SOCKETS_NAMESPACE
+} // namespace SOCKETS_NAMESPACE {
+#endif
+
diff --git a/Sockets/Ipv4Address.h b/Sockets/Ipv4Address.h
new file mode 100644
index 0000000..b58c2ce
--- /dev/null
+++ b/Sockets/Ipv4Address.h
@@ -0,0 +1,98 @@
+/**
+ ** \file Ipv4Address.h
+ ** \date 2006-09-21
+ ** \author grymse@alhem.net
+**/
+/*
+Copyright (C) 2007 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.
+*/
+#ifndef _SOCKETS_Ipv4Address_H
+#define _SOCKETS_Ipv4Address_H
+
+#include "sockets-config.h"
+#include "SocketAddress.h"
+
+
+#ifdef SOCKETS_NAMESPACE
+namespace SOCKETS_NAMESPACE {
+#endif
+
+
+/* Ipv4 address implementation.
+ \ingroup basic */
+class Ipv4Address : public SocketAddress
+{
+public:
+ /** Create empty Ipv4 address structure.
+ \param port Port number */
+ Ipv4Address(port_t port = 0);
+ /** Create Ipv4 address structure.
+ \param a Socket address in network byte order (as returned by Utility::u2ip)
+ \param port Port number in host byte order */
+ Ipv4Address(ipaddr_t a,port_t port);
+ /** Create Ipv4 address structure.
+ \param a Socket address in network byte order
+ \param port Port number in host byte order */
+ Ipv4Address(struct in_addr& a,port_t port);
+ /** Create Ipv4 address structure.
+ \param host Hostname to be resolved
+ \param port Port number in host byte order */
+ Ipv4Address(const std::string& host,port_t port);
+ Ipv4Address(struct sockaddr_in&);
+ ~Ipv4Address();
+
+ // SocketAddress implementation
+
+ operator struct sockaddr *();
+ operator socklen_t();
+ bool operator==(SocketAddress&);
+
+ void SetPort(port_t port);
+ port_t GetPort();
+
+ void SetAddress(struct sockaddr *sa);
+ int GetFamily();
+
+ bool IsValid();
+ std::auto_ptr<SocketAddress> GetCopy();
+
+ /** Convert address struct to text. */
+ std::string Convert(bool include_port = false);
+ std::string Reverse();
+
+ /** 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);
+
+private:
+ Ipv4Address(const Ipv4Address& ) {} // copy constructor
+ Ipv4Address& operator=(const Ipv4Address& ) { return *this; } // assignment operator
+ struct sockaddr_in m_addr;
+ bool m_valid;
+};
+
+
+
+
+#ifdef SOCKETS_NAMESPACE
+} // namespace SOCKETS_NAMESPACE {
+#endif
+#endif // _SOCKETS_Ipv4Address_H
+
diff --git a/Sockets/Ipv6Address.cpp b/Sockets/Ipv6Address.cpp
new file mode 100644
index 0000000..2e0f1e9
--- /dev/null
+++ b/Sockets/Ipv6Address.cpp
@@ -0,0 +1,270 @@
+/**
+ ** \file Ipv6Address.cpp
+ ** \date 2006-09-21
+ ** \author grymse@alhem.net
+**/
+/*
+Copyright (C) 2007 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.
+*/
+#include "Ipv6Address.h"
+#ifdef ENABLE_IPV6
+
+#include "Utility.h"
+#include "Parse.h"
+#ifndef _WIN32
+#include <netdb.h>
+#endif
+#ifdef IPPROTO_IPV6
+
+#ifdef SOCKETS_NAMESPACE
+namespace SOCKETS_NAMESPACE {
+#endif
+
+
+Ipv6Address::Ipv6Address(port_t port) : m_valid(true)
+{
+ memset(&m_addr, 0, sizeof(m_addr));
+ m_addr.sin6_family = AF_INET6;
+ m_addr.sin6_port = htons( port );
+}
+
+
+Ipv6Address::Ipv6Address(struct in6_addr& a,port_t port) : m_valid(true)
+{
+ memset(&m_addr, 0, sizeof(m_addr));
+ m_addr.sin6_family = AF_INET6;
+ m_addr.sin6_port = htons( port );
+ m_addr.sin6_addr = a;
+}
+
+
+Ipv6Address::Ipv6Address(const std::string& host,port_t port) : m_valid(false)
+{
+ memset(&m_addr, 0, sizeof(m_addr));
+ m_addr.sin6_family = AF_INET6;
+ m_addr.sin6_port = htons( port );
+ {
+ struct in6_addr a;
+ if (Utility::u2ip(host, a))
+ {
+ m_addr.sin6_addr = a;
+ m_valid = true;
+ }
+ }
+}
+
+
+Ipv6Address::Ipv6Address(struct sockaddr_in6& sa)
+{
+ m_addr = sa;
+ m_valid = sa.sin6_family == AF_INET6;
+}
+
+
+Ipv6Address::~Ipv6Address()
+{
+}
+
+
+Ipv6Address::operator struct sockaddr *()
+{
+ return (struct sockaddr *)&m_addr;
+}
+
+
+Ipv6Address::operator socklen_t()
+{
+ return sizeof(struct sockaddr_in6);
+}
+
+
+void Ipv6Address::SetPort(port_t port)
+{
+ m_addr.sin6_port = htons( port );
+}
+
+
+port_t Ipv6Address::GetPort()
+{
+ return ntohs( m_addr.sin6_port );
+}
+
+
+bool Ipv6Address::Resolve(const std::string& hostname,struct in6_addr& a)
+{
+ struct sockaddr_in6 sa;
+ memset(&a, 0, sizeof(a));
+ if (Utility::isipv6(hostname))
+ {
+ if (!Utility::u2ip(hostname, sa, AI_NUMERICHOST))
+ return false;
+ a = sa.sin6_addr;
+ return true;
+ }
+ if (!Utility::u2ip(hostname, sa))
+ return false;
+ a = sa.sin6_addr;
+ return true;
+}
+
+
+bool Ipv6Address::Reverse(struct in6_addr& a,std::string& name)
+{
+ struct sockaddr_in6 sa;
+ memset(&sa, 0, sizeof(sa));
+ sa.sin6_family = AF_INET6;
+ sa.sin6_addr = a;
+ return Utility::reverse((struct sockaddr *)&sa, sizeof(sa), name);
+}
+
+
+std::string Ipv6Address::Convert(bool include_port)
+{
+ if (include_port)
+ return Convert(m_addr.sin6_addr) + ":" + Utility::l2string(GetPort());
+ return Convert(m_addr.sin6_addr);
+}
+
+
+std::string Ipv6Address::Convert(struct in6_addr& a,bool mixed)
+{
+ char slask[100]; // l2ip temporary
+ *slask = 0;
+ unsigned int prev = 0;
+ bool skipped = false;
+ bool ok_to_skip = true;
+ if (mixed)
+ {
+ unsigned short x;
+ unsigned short addr16[8];
+ memcpy(addr16, &a, sizeof(addr16));
+ for (size_t i = 0; i < 6; i++)
+ {
+ x = ntohs(addr16[i]);
+ if (*slask && (x || !ok_to_skip || prev))
+ strcat(slask,":");
+ if (x || !ok_to_skip)
+ {
+ sprintf(slask + strlen(slask),"%x", x);
+ if (x && skipped)
+ ok_to_skip = false;
+ }
+ else
+ {
+ skipped = true;
+ }
+ prev = x;
+ }
+ x = ntohs(addr16[6]);
+ sprintf(slask + strlen(slask),":%u.%u",x / 256,x & 255);
+ x = ntohs(addr16[7]);
+ sprintf(slask + strlen(slask),".%u.%u",x / 256,x & 255);
+ }
+ else
+ {
+ struct sockaddr_in6 sa;
+ memset(&sa, 0, sizeof(sa));
+ sa.sin6_family = AF_INET6;
+ sa.sin6_addr = a;
+ std::string name;
+ Utility::reverse((struct sockaddr *)&sa, sizeof(sa), name, NI_NUMERICHOST);
+ return name;
+ }
+ return slask;
+}
+
+
+void Ipv6Address::SetAddress(struct sockaddr *sa)
+{
+ memcpy(&m_addr, sa, sizeof(struct sockaddr_in6));
+}
+
+
+int Ipv6Address::GetFamily()
+{
+ return m_addr.sin6_family;
+}
+
+
+void Ipv6Address::SetFlowinfo(uint32_t x)
+{
+ m_addr.sin6_flowinfo = x;
+}
+
+
+uint32_t Ipv6Address::GetFlowinfo()
+{
+ return m_addr.sin6_flowinfo;
+}
+
+
+#ifndef _WIN32
+void Ipv6Address::SetScopeId(uint32_t x)
+{
+ m_addr.sin6_scope_id = x;
+}
+
+
+uint32_t Ipv6Address::GetScopeId()
+{
+ return m_addr.sin6_scope_id;
+}
+#endif
+
+
+bool Ipv6Address::IsValid()
+{
+ return m_valid;
+}
+
+
+bool Ipv6Address::operator==(SocketAddress& a)
+{
+ if (a.GetFamily() != GetFamily())
+ return false;
+ if ((socklen_t)a != sizeof(m_addr))
+ return false;
+ struct sockaddr *sa = a;
+ struct sockaddr_in6 *p = (struct sockaddr_in6 *)sa;
+ if (p -> sin6_port != m_addr.sin6_port)
+ return false;
+ if (memcmp(&p -> sin6_addr, &m_addr.sin6_addr, sizeof(struct in6_addr)))
+ return false;
+ return true;
+}
+
+
+std::auto_ptr<SocketAddress> Ipv6Address::GetCopy()
+{
+ return std::auto_ptr<SocketAddress>(new Ipv6Address(m_addr));
+}
+
+
+std::string Ipv6Address::Reverse()
+{
+ std::string tmp;
+ Reverse(m_addr.sin6_addr, tmp);
+ return tmp;
+}
+
+
+#ifdef SOCKETS_NAMESPACE
+} // namespace SOCKETS_NAMESPACE {
+#endif
+#endif // IPPROTO_IPV6
+#endif // ENABLE_IPV6
+
diff --git a/Sockets/Ipv6Address.h b/Sockets/Ipv6Address.h
new file mode 100644
index 0000000..a071141
--- /dev/null
+++ b/Sockets/Ipv6Address.h
@@ -0,0 +1,107 @@
+/**
+ ** \file Ipv6Address.h
+ ** \date 2006-09-21
+ ** \author grymse@alhem.net
+**/
+/*
+Copyright (C) 2007 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.
+*/
+#ifndef _SOCKETS_Ipv6Address_H
+#define _SOCKETS_Ipv6Address_H
+#include "sockets-config.h"
+#ifdef ENABLE_IPV6
+
+#include "SocketAddress.h"
+#ifdef IPPROTO_IPV6
+#if defined( _WIN32) && !defined(__CYGWIN__)
+typedef unsigned __int32 uint32_t;
+#endif
+
+#ifdef SOCKETS_NAMESPACE
+namespace SOCKETS_NAMESPACE {
+#endif
+
+
+/** Ipv6 address implementation.
+ \ingroup basic */
+class Ipv6Address : public SocketAddress
+{
+public:
+ /** Create empty Ipv6 address structure.
+ \param port Port number */
+ Ipv6Address(port_t port = 0);
+ /** Create Ipv6 address structure.
+ \param a Socket address in network byte order
+ \param port Port number in host byte order */
+ Ipv6Address(struct in6_addr& a,port_t port);
+ /** Create Ipv6 address structure.
+ \param host Hostname to be resolved
+ \param port Port number in host byte order */
+ Ipv6Address(const std::string& host,port_t port);
+ Ipv6Address(struct sockaddr_in6&);
+ ~Ipv6Address();
+
+ // SocketAddress implementation
+
+ operator struct sockaddr *();
+ operator socklen_t();
+ bool operator==(SocketAddress&);
+
+ void SetPort(port_t port);
+ port_t GetPort();
+
+ void SetAddress(struct sockaddr *sa);
+ int GetFamily();
+
+ bool IsValid();
+ std::auto_ptr<SocketAddress> GetCopy();
+
+ /** Convert address struct to text. */
+ std::string Convert(bool include_port = false);
+ std::string Reverse();
+
+ /** 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);
+
+ void SetFlowinfo(uint32_t);
+ uint32_t GetFlowinfo();
+#ifndef _WIN32
+ void SetScopeId(uint32_t);
+ uint32_t GetScopeId();
+#endif
+
+private:
+ Ipv6Address(const Ipv6Address& ) {} // copy constructor
+ Ipv6Address& operator=(const Ipv6Address& ) { return *this; } // assignment operator
+ struct sockaddr_in6 m_addr;
+ bool m_valid;
+};
+
+
+
+
+#ifdef SOCKETS_NAMESPACE
+} // namespace SOCKETS_NAMESPACE {
+#endif
+#endif // IPPROTO_IPV6
+#endif // ENABLE_IPV6
+#endif // _SOCKETS_Ipv6Address_H
+
diff --git a/Sockets/ListenSocket.h b/Sockets/ListenSocket.h
new file mode 100644
index 0000000..f4edc37
--- /dev/null
+++ b/Sockets/ListenSocket.h
@@ -0,0 +1,420 @@
+/** \file ListenSocket.h
+ ** \date 2004-02-13
+ ** \author grymse@alhem.net
+**/
+/*
+Copyright (C) 2004-2007 Anders Hedstrom
+
+This library is made available under the terms of the GNU GPL.
+
+If you would like to use this library in a closed-source application,
+a separate license agreement is available. For information about
+the closed-source license agreement for the C++ sockets library,
+please visit http://www.alhem.net/Sockets/license.html and/or
+email license@alhem.net.
+
+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.
+*/
+#ifndef _SOCKETS_ListenSocket_H
+#define _SOCKETS_ListenSocket_H
+#include "sockets-config.h"
+
+#ifdef _WIN32
+#include <stdlib.h>
+#else
+#include <errno.h>
+#endif
+
+#include "ISocketHandler.h"
+#include "Socket.h"
+#include "Utility.h"
+#include "SctpSocket.h"
+#include "Ipv4Address.h"
+#include "Ipv6Address.h"
+#ifdef ENABLE_EXCEPTIONS
+#include "Exception.h"
+#endif
+
+#ifdef SOCKETS_NAMESPACE
+namespace SOCKETS_NAMESPACE {
+#endif
+
+
+/** Binds incoming port number to new Socket class X.
+ \ingroup basic */
+template <class X>
+class ListenSocket : public Socket
+{
+public:
+ /** Constructor.
+ \param h ISocketHandler reference
+ \param use_creator Optional use of creator (default true) */
+ ListenSocket(ISocketHandler& h,bool use_creator = true) : Socket(h), m_depth(0), m_creator(NULL)
+ ,m_bHasCreate(false)
+ {
+ if (use_creator)
+ {
+ m_creator = new X(h);
+ Socket *tmp = m_creator -> Create();
+ if (tmp && dynamic_cast<X *>(tmp))
+ {
+ m_bHasCreate = true;
+ }
+ if (tmp)
+ {
+ delete tmp;
+ }
+ }
+ }
+ ~ListenSocket() {
+ if (m_creator)
+ {
+ delete m_creator;
+ }
+ }
+
+ /** Close file descriptor. */
+ int Close() {
+ if (GetSocket() != INVALID_SOCKET)
+ {
+ closesocket(GetSocket());
+ }
+ return 0;
+ }
+
+ /** Bind and listen to any interface.
+ \param port Port (0 is random)
+ \param depth Listen queue depth */
+ int Bind(port_t port,int depth = 20) {
+#ifdef ENABLE_IPV6
+#ifdef IPPROTO_IPV6
+ if (IsIpv6())
+ {
+ Ipv6Address ad(port);
+ return Bind(ad, depth);
+ }
+ else
+#endif
+#endif
+ {
+ Ipv4Address ad(port);
+ return Bind(ad, depth);
+ }
+ }
+
+ int Bind(SocketAddress& ad,int depth) {
+#ifdef USE_SCTP
+ if (dynamic_cast<SctpSocket *>(m_creator))
+ {
+ return Bind(ad, "sctp", depth);
+ }
+#endif
+ return Bind(ad, "tcp", depth);
+ }
+
+ /** Bind and listen to any interface, with optional protocol.
+ \param port Port (0 is random)
+ \param protocol Network protocol
+ \param depth Listen queue depth */
+ int Bind(port_t port,const std::string& protocol,int depth = 20) {
+#ifdef ENABLE_IPV6
+#ifdef IPPROTO_IPV6
+ if (IsIpv6())
+ {
+ Ipv6Address ad(port);
+ return Bind(ad, protocol, depth);
+ }
+ else
+#endif
+#endif
+ {
+ Ipv4Address ad(port);
+ return Bind(ad, protocol, depth);
+ }
+ }
+
+ /** Bind and listen to specific interface.
+ \param intf Interface hostname
+ \param port Port (0 is random)
+ \param depth Listen queue depth */
+ int Bind(const std::string& intf,port_t port,int depth = 20) {
+#ifdef ENABLE_IPV6
+#ifdef IPPROTO_IPV6
+ if (IsIpv6())
+ {
+ Ipv6Address ad(intf, port);
+ if (ad.IsValid())
+ {
+ return Bind(ad, depth);
+ }
+ Handler().LogError(this, "Bind", 0, "name resolution of interface name failed", LOG_LEVEL_FATAL);
+ return -1;
+ }
+ else
+#endif
+#endif
+ {
+ Ipv4Address ad(intf, port);
+ if (ad.IsValid())
+ {
+ return Bind(ad, depth);
+ }
+ Handler().LogError(this, "Bind", 0, "name resolution of interface name failed", LOG_LEVEL_FATAL);
+ return -1;
+ }
+ }
+
+ /** Bind and listen to specific interface.
+ \param intf Interface hostname
+ \param port Port (0 is random)
+ \param protocol Network protocol
+ \param depth Listen queue depth */
+ int Bind(const std::string& intf,port_t port,const std::string& protocol,int depth = 20) {
+#ifdef ENABLE_IPV6
+#ifdef IPPROTO_IPV6
+ if (IsIpv6())
+ {
+ Ipv6Address ad(intf, port);
+ if (ad.IsValid())
+ {
+ return Bind(ad, protocol, depth);
+ }
+ Handler().LogError(this, "Bind", 0, "name resolution of interface name failed", LOG_LEVEL_FATAL);
+ return -1;
+ }
+ else
+#endif
+#endif
+ {
+ Ipv4Address ad(intf, port);
+ if (ad.IsValid())
+ {
+ return Bind(ad, protocol, depth);
+ }
+ Handler().LogError(this, "Bind", 0, "name resolution of interface name failed", LOG_LEVEL_FATAL);
+ return -1;
+ }
+ }
+
+ /** Bind and listen to ipv4 interface.
+ \param a Ipv4 interface address
+ \param port Port (0 is random)
+ \param depth Listen queue depth */
+ int Bind(ipaddr_t a,port_t port,int depth = 20) {
+ Ipv4Address ad(a, port);
+#ifdef USE_SCTP
+ if (dynamic_cast<SctpSocket *>(m_creator))
+ {
+ return Bind(ad, "sctp", depth);
+ }
+#endif
+ return Bind(ad, "tcp", depth);
+ }
+ /** Bind and listen to ipv4 interface.
+ \param a Ipv4 interface address
+ \param port Port (0 is random)
+ \param protocol Network protocol
+ \param depth Listen queue depth */
+ int Bind(ipaddr_t a,port_t port,const std::string& protocol,int depth) {
+ Ipv4Address ad(a, port);
+ return Bind(ad, protocol, depth);
+ }
+
+#ifdef ENABLE_IPV6
+#ifdef IPPROTO_IPV6
+ /** Bind and listen to ipv6 interface.
+ \param a Ipv6 interface address
+ \param port Port (0 is random)
+ \param depth Listen queue depth */
+ int Bind(in6_addr a,port_t port,int depth = 20) {
+ Ipv6Address ad(a, port);
+#ifdef USE_SCTP
+ if (dynamic_cast<SctpSocket *>(m_creator))
+ {
+ return Bind(ad, "sctp", depth);
+ }
+#endif
+ return Bind(ad, "tcp", depth);
+ }
+ /** Bind and listen to ipv6 interface.
+ \param a Ipv6 interface address
+ \param port Port (0 is random)
+ \param protocol Network protocol
+ \param depth Listen queue depth */
+ int Bind(in6_addr a,port_t port,const std::string& protocol,int depth) {
+ Ipv6Address ad(a, port);
+ return Bind(ad, protocol, depth);
+ }
+#endif
+#endif
+
+ /** Bind and listen to network interface.
+ \param ad Interface address
+ \param protocol Network protocol
+ \param depth Listen queue depth */
+ int Bind(SocketAddress& ad,const std::string& protocol,int depth) {
+ SOCKET s;
+ if ( (s = CreateSocket(ad.GetFamily(), SOCK_STREAM, protocol)) == INVALID_SOCKET)
+ {
+ return -1;
+ }
+ if (bind(s, ad, ad) == -1)
+ {
+ Handler().LogError(this, "bind", Errno, StrError(Errno), LOG_LEVEL_FATAL);
+ closesocket(s);
+#ifdef ENABLE_EXCEPTIONS
+ throw Exception("bind() failed for port " + Utility::l2string(ad.GetPort()) + ": " + StrError(Errno));
+#endif
+ return -1;
+ }
+ if (listen(s, depth) == -1)
+ {
+ Handler().LogError(this, "listen", Errno, StrError(Errno), LOG_LEVEL_FATAL);
+ closesocket(s);
+#ifdef ENABLE_EXCEPTIONS
+ throw Exception("listen() failed for port " + Utility::l2string(ad.GetPort()) + ": " + StrError(Errno));
+#endif
+ return -1;
+ }
+ m_depth = depth;
+ Attach(s);
+ return 0;
+ }
+
+ /** Return assigned port number. */
+ port_t GetPort()
+ {
+ return GetSockPort();
+ }
+
+ /** Return listen queue depth. */
+ int GetDepth()
+ {
+ return m_depth;
+ }
+
+ /** OnRead on a ListenSocket receives an incoming connection. */
+ void OnRead()
+ {
+ struct sockaddr sa;
+ socklen_t sa_len = sizeof(struct sockaddr);
+ SOCKET a_s = accept(GetSocket(), &sa, &sa_len);
+
+ if (a_s == INVALID_SOCKET)
+ {
+ Handler().LogError(this, "accept", Errno, StrError(Errno), LOG_LEVEL_ERROR);
+ return;
+ }
+ if (!Handler().OkToAccept(this))
+ {
+ Handler().LogError(this, "accept", -1, "Not OK to accept", LOG_LEVEL_WARNING);
+ closesocket(a_s);
+ return;
+ }
+ if (Handler().GetCount() >= FD_SETSIZE)
+ {
+ Handler().LogError(this, "accept", (int)Handler().GetCount(), "ISocketHandler fd_set limit reached", LOG_LEVEL_FATAL);
+ closesocket(a_s);
+ return;
+ }
+ Socket *tmp = m_bHasCreate ? m_creator -> Create() : new X(Handler());
+#ifdef ENABLE_IPV6
+ tmp -> SetIpv6( IsIpv6() );
+#endif
+ tmp -> SetParent(this);
+ tmp -> Attach(a_s);
+ tmp -> SetNonblocking(true);
+ {
+#ifdef ENABLE_IPV6
+#ifdef IPPROTO_IPV6
+ if (sa_len == sizeof(struct sockaddr_in6))
+ {
+ struct sockaddr_in6 *p = (struct sockaddr_in6 *)&sa;
+ if (p -> sin6_family == AF_INET6)
+ {
+ Ipv6Address ad(p -> sin6_addr,ntohs(p -> sin6_port));
+ ad.SetFlowinfo(p -> sin6_flowinfo);
+#ifndef _WIN32
+ ad.SetScopeId(p -> sin6_scope_id);
+#endif
+ tmp -> SetRemoteAddress(ad);
+ }
+ }
+#endif
+#endif
+ if (sa_len == sizeof(struct sockaddr_in))
+ {
+ struct sockaddr_in *p = (struct sockaddr_in *)&sa;
+ if (p -> sin_family == AF_INET)
+ {
+ Ipv4Address ad(p -> sin_addr,ntohs(p -> sin_port));
+ tmp -> SetRemoteAddress(ad);
+ }
+ }
+ }
+ tmp -> SetConnected(true);
+ tmp -> Init();
+ tmp -> SetDeleteByHandler(true);
+ Handler().Add(tmp);
+#ifdef HAVE_OPENSSL
+ if (tmp -> IsSSL()) // SSL Enabled socket
+ {
+ // %! OnSSLAccept calls SSLNegotiate that can finish in this one call.
+ // %! If that happens and negotiation fails, the 'tmp' instance is
+ // %! still added to the list of active sockets in the sockethandler.
+ // %! See bugfix for this in SocketHandler::Select - don't Set rwx
+ // %! flags if CloseAndDelete() flag is true.
+ // %! An even better fugbix (see TcpSocket::OnSSLAccept) now avoids
+ // %! the Add problem altogether, so ignore the above.
+ // %! (OnSSLAccept does no longer call SSLNegotiate().)
+ tmp -> OnSSLAccept();
+ }
+ else
+#endif
+ {
+ tmp -> OnAccept();
+ }
+ }
+
+ /** Please don't use this method.
+ "accept()" is handled automatically in the OnRead() method. */
+ virtual SOCKET Accept(SOCKET socket, struct sockaddr *saptr, socklen_t *lenptr)
+ {
+ return accept(socket, saptr, lenptr);
+ }
+
+ bool HasCreator() { return m_bHasCreate; }
+
+ void OnOptions(int,int,int,SOCKET) {
+ SetSoReuseaddr(true);
+ }
+
+protected:
+ ListenSocket(const ListenSocket& s) : Socket(s) {}
+private:
+ ListenSocket& operator=(const ListenSocket& ) { return *this; }
+ int m_depth;
+ X *m_creator;
+ bool m_bHasCreate;
+};
+
+
+
+#ifdef SOCKETS_NAMESPACE
+}
+#endif
+
+#endif // _SOCKETS_ListenSocket_H
+
diff --git a/Sockets/Lock.cpp b/Sockets/Lock.cpp
new file mode 100644
index 0000000..3f7902e
--- /dev/null
+++ b/Sockets/Lock.cpp
@@ -0,0 +1,55 @@
+/** \file Lock.cpp
+ ** \date 2005-08-22
+ ** \author grymse@alhem.net
+**/
+/*
+Copyright (C) 2005,2007 Anders Hedstrom
+
+This library is made available under the terms of the GNU GPL.
+
+If you would like to use this library in a closed-source application,
+a separate license agreement is available. For information about
+the closed-source license agreement for the C++ sockets library,
+please visit http://www.alhem.net/Sockets/license.html and/or
+email license@alhem.net.
+
+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.
+*/
+#include "Mutex.h"
+#include "Lock.h"
+
+#ifdef SOCKETS_NAMESPACE
+namespace SOCKETS_NAMESPACE {
+#endif
+
+
+Lock::Lock(Mutex& m) : m_mutex(m)
+{
+ m_mutex.Lock();
+}
+
+
+Lock::~Lock()
+{
+ m_mutex.Unlock();
+}
+
+
+
+
+#ifdef SOCKETS_NAMESPACE
+}
+#endif
+
diff --git a/Sockets/Lock.h b/Sockets/Lock.h
new file mode 100644
index 0000000..71fdd5e
--- /dev/null
+++ b/Sockets/Lock.h
@@ -0,0 +1,59 @@
+/** \file Lock.h
+ ** \date 2005-08-22
+ ** \author grymse@alhem.net
+**/
+/*
+Copyright (C) 2005,2007 Anders Hedstrom
+
+This library is made available under the terms of the GNU GPL.
+
+If you would like to use this library in a closed-source application,
+a separate license agreement is available. For information about
+the closed-source license agreement for the C++ sockets library,
+please visit http://www.alhem.net/Sockets/license.html and/or
+email license@alhem.net.
+
+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.
+*/
+#ifndef _SOCKETS_Lock_H
+#define _SOCKETS_Lock_H
+
+#include "sockets-config.h"
+#ifdef SOCKETS_NAMESPACE
+namespace SOCKETS_NAMESPACE {
+#endif
+
+class Mutex;
+
+/** Mutex encapsulation class.
+ \ingroup threading */
+class Lock
+{
+public:
+ Lock(Mutex&);
+ ~Lock();
+
+private:
+ Mutex& m_mutex;
+};
+
+
+
+
+#ifdef SOCKETS_NAMESPACE
+}
+#endif
+#endif // _SOCKETS_Lock_H
+
diff --git a/Sockets/Makefile b/Sockets/Makefile
new file mode 100644
index 0000000..631501d
--- /dev/null
+++ b/Sockets/Makefile
@@ -0,0 +1,154 @@
+# platforms:
+# linux-x86-32
+# win32-cygwin
+# solaris9-sparc-64
+# macosx
+# solaris8
+PLATFORM = linux-x86-32
+IPPROTO_IPV6 = yes
+
+# .h files installed to $(PREFIX)/include/Sockets
+# static lib .a files installed to $(PREFIX)/lib
+PREFIX = /usr/local
+
+# include paths
+INCLUDE =
+
+include Makefile.version
+
+# CXX, CFLAGS, LIBS
+include Makefile.Defines.$(PLATFORM)
+
+# uncomment these lines if the library should be in its own namespace
+CFLAGS += -DSOCKETS_NAMESPACE=sockets
+CFLAGS += -DSOCKETS_NAMESPACE_STR='"sockets"'
+
+# Enable insane amounts of debug output to stdout/stderr:
+#CFLAGS += -D_DEBUG
+#CFLAGS += -DIPPROTO_IPV6
+
+
+CPPFLAGS = $(CFLAGS)
+
+PROGS = Sockets-config
+
+all: libSockets.a $(PROGS)
+
+libSockets.a: $(OBJS)
+ ar cru $@ $(OBJS)
+ ranlib $@
+
+Sockets-config: Sockets-config.o
+ $(CXX) -o $@ $^
+
+clean:
+ rm -f *.o *~ slask *.d $(PROGS) *.a */*~
+
+-include *.d
+
+
+# everything which follows is www.alhem.net/Sockets website maintenance stuff, please ignore
+HTDOCS = /usr/local/apache/www.alhem.net/htdocs
+
+diff:
+ diff -b -B -C 3 /usr/src/Sockets-$(DIFF_VERSION) . | \
+ /usr/local/bin/d2html > \
+ $(HTDOCS)/Sockets/latest_diff.html
+
+install: all
+ @mkdir -p $(PREFIX)/lib
+ cp libSockets.a $(PREFIX)/lib
+ @mkdir -p $(PREFIX)/include/Sockets
+ cp -a *.h $(PREFIX)/include/Sockets
+ @rm -f $(PREFIX)/include/Sockets/SSLSocket.*
+ @rm -f $(PREFIX)/include/Sockets/HttpsGetSocket.*
+ @rm -f $(PREFIX)/include/Sockets/HttpsSocket.*
+ @rm -f $(PREFIX)/include/Sockets/EventSocket.*
+ @rm -f $(PREFIX)/include/Sockets/PoolSocket.*
+ @rm -f $(PREFIX)/include/Sockets/SocketThread.*
+ @rm -f $(PREFIX)/include/Sockets/CircularBuffer.*
+ @rm -f $(PREFIX)/include/Sockets/*Crypt.h
+ @rm -f $(PREFIX)/include/Sockets/CTcpSocket.h
+ @rm -f $(PREFIX)/include/Sockets/Min*Socket.h
+ @rm -f $(PREFIX)/include/Sockets/Min*Handler.h
+ @rm -f $(PREFIX)/include/Sockets/Uid.h
+ @mkdir -p $(PREFIX)/bin
+ install Sockets-config $(PREFIX)/bin
+
+# no binary files, zip will translate lf to cr lf
+FILES = *.h *.cpp Makefile Makefile.* Project/*.ds* \
+ README.macosx gpl.txt mkdot.sh \
+ Project.net/Sockets/*.vcproj Project.net/Sockets/*.sln \
+ Project.net/Test/*.vcproj \
+ DevCpp/*.dev tests/Makefile tests/*.cpp \
+ OSX.zip
+
+tar: clean
+ rm -f MinderSocket_T.h
+ rm -f uuid.h
+ rm -f Stdin.*
+ rm -f sockets_test.cpp
+ rm -f ListenSocketBase.*
+ rm -f CircularBuffer.*
+ rm -f ICrypt.* NullCrypt.* CTcpSocket.*
+ rm -f Min*Socket.* Min*Handler.*
+ rm -f Uid.*
+ tar czf Sockets-$(VERSION).tar.gz $(FILES)
+ /usr/local/bin/tarfix.sh Sockets-$(VERSION)
+ cp Sockets-$(VERSION).tar.gz $(HTDOCS)/Sockets
+ cp Sockets-$(VERSION).zip $(HTDOCS)/Sockets
+ cp tests/sockets_test.cpp /usr/local/apache/www.alhem.net/htdocs/Sockets/
+# $(MAKE) -C ../SocketsLite tar
+
+tmptar: clean
+ rm -f MinderSocket_T.h
+ rm -f uuid.h
+ rm -f Stdin.*
+ rm -f sockets_test.cpp
+ rm -f ListenSocketBase.*
+ rm -f CircularBuffer.*
+ rm -f ICrypt.* NullCrypt.* CTcpSocket.*
+ rm -f Min*Socket.* Min*Handler.*
+ rm -f Uid.*
+ tar czf Sockets-$(VERSION).tar.gz $(FILES)
+ /usr/local/bin/tarfix.sh Sockets-$(VERSION)
+ cp Sockets-$(VERSION).tar.gz $(HTDOCS)/Sockets-tmp
+ cp Sockets-$(VERSION).zip $(HTDOCS)/Sockets-tmp
+ cp tests/sockets_test.cpp /usr/local/apache/www.alhem.net/htdocs/Sockets-tmp
+ $(MAKE) -C ../SocketsLite tmptar
+
+docs: clean
+ doxygen dox2.cfg
+ rm -f MinderSocket_T.h
+ rm -f uuid.h
+ rm -f Stdin.*
+ rm -f sockets_test.cpp
+ rm -f ListenSocketBase.*
+ rm -f CircularBuffer.*
+ rm -f ICrypt.* NullCrypt.* CTcpSocket.*
+ rm -f Min*Socket.* Min*Handler.*
+ rm -f Uid.*
+ rm -f tests/*.cpp
+ ./mkdot.sh
+ rm -rf /usr/local/apache/www.alhem.net/htdocs/Sockets/html
+ doxygen doxygen.cfg
+ ./packdocs.sh Sockets-$(VERSION)-doxygendocs
+ cvs up
+# $(MAKE) -C ../SocketsLite docs
+
+tmpdocs: clean
+ rm -f MinderSocket_T.h
+ rm -f uuid.h
+ rm -f Stdin.*
+ rm -f sockets_test.cpp
+ rm -f ListenSocketBase.*
+ rm -f CircularBuffer.*
+ rm -f ICrypt.* NullCrypt.* CTcpSocket.*
+ rm -f Min*Socket.* Min*Handler.*
+ rm -f Uid.*
+ rm -f tests/*.cpp
+ ./mkdot-tmp.sh
+ rm -rf /usr/local/apache/www.alhem.net/htdocs/Sockets-tmp/html
+ doxygen doxygen-tmp.cfg
+ cvs up
+ $(MAKE) -C ../SocketsLite tmpdocs
diff --git a/Sockets/Makefile.Defines.linux-x86-32 b/Sockets/Makefile.Defines.linux-x86-32
new file mode 100644
index 0000000..df06d6b
--- /dev/null
+++ b/Sockets/Makefile.Defines.linux-x86-32
@@ -0,0 +1,28 @@
+CXX = g++
+
+CFLAGS += -Wall -g $(INCLUDE) -MD -D_VERSION='"$(VERSION)"'
+
+# turn off optimization if compiling with gcc 2.9.x:
+#CFLAGS += -O0
+CFLAGS += -O2
+
+
+# uncomment depending on your operating system
+CFLAGS += -DLINUX
+#CFLAGS += -DMACOSX
+# solaris > 8
+#CFLAGS += -DSOLARIS
+# solaris 8
+#CFLAGS += -DSOLARIS8
+# windows and/or cygwin
+#CFLAGS += -D_WIN32
+# cygwin
+#CFLAGS += -D__CYGWIN__
+
+
+LIBS += \
+ -lssl -lcrypto \
+ -lpthread
+
+OBJS += Semaphore.o
+
diff --git a/Sockets/Makefile.Defines.macosx b/Sockets/Makefile.Defines.macosx
new file mode 100644
index 0000000..9b54559
--- /dev/null
+++ b/Sockets/Makefile.Defines.macosx
@@ -0,0 +1,28 @@
+CXX = g++
+
+CFLAGS += -Wall -g $(INCLUDE) -MD -D_VERSION='"$(VERSION)"'
+
+# turn off optimization if compiling with gcc 2.9.x:
+#CFLAGS += -O0
+CFLAGS += -O2
+
+
+# uncomment depending on your operating system
+#CFLAGS += -DLINUX
+CFLAGS += -DMACOSX
+# solaris > 8
+#CFLAGS += -DSOLARIS
+# solaris 8
+#CFLAGS += -DSOLARIS8
+# windows and/or cygwin
+#CFLAGS += -D_WIN32
+# cygwin
+#CFLAGS += -D__CYGWIN__
+
+
+LIBS += \
+ -lssl -lcrypto \
+ -lpthread
+
+OBJS += Semaphore.o
+
diff --git a/Sockets/Makefile.Defines.solaris8 b/Sockets/Makefile.Defines.solaris8
new file mode 100644
index 0000000..ec31056
--- /dev/null
+++ b/Sockets/Makefile.Defines.solaris8
@@ -0,0 +1,29 @@
+CXX = /opt/SUNWspro/bin/CC
+
+CFLAGS += -g $(INCLUDE) -MD -D_VERSION='"$(VERSION)"'
+CFLAGS += -features=rtti -mt
+
+# turn off optimization if compiling with gcc 2.9.x:
+#CFLAGS += -O0
+CFLAGS += -O2
+
+
+# uncomment depending on your operating system
+#CFLAGS += -DLINUX
+#CFLAGS += -DMACOSX
+# solaris > 8
+#CFLAGS += -DSOLARIS
+# solaris 8
+CFLAGS += -DSOLARIS8
+# windows and/or cygwin
+#CFLAGS += -D_WIN32
+# cygwin
+#CFLAGS += -D__CYGWIN__
+
+
+LIBS += \
+ -lssl -lcrypto \
+ -lpthread
+
+OBJS += Semaphore.o
+
diff --git a/Sockets/Makefile.Defines.solaris9-sparc-64 b/Sockets/Makefile.Defines.solaris9-sparc-64
new file mode 100644
index 0000000..42fa8c4
--- /dev/null
+++ b/Sockets/Makefile.Defines.solaris9-sparc-64
@@ -0,0 +1,29 @@
+CXX = /opt/SUNWspro/bin/CC
+
+CFLAGS += -g $(INCLUDE) -MD -D_VERSION='"$(VERSION)"'
+CFLAGS += -features=rtti -mt
+
+# turn off optimization if compiling with gcc 2.9.x:
+#CFLAGS += -O0
+CFLAGS += -O2
+
+
+# uncomment depending on your operating system
+#CFLAGS += -DLINUX
+#CFLAGS += -DMACOSX
+# solaris > 8
+CFLAGS += -DSOLARIS
+# solaris 8
+#CFLAGS += -DSOLARIS8
+# windows and/or cygwin
+#CFLAGS += -D_WIN32
+# cygwin
+#CFLAGS += -D__CYGWIN__
+
+
+LIBS += \
+ -lssl -lcrypto \
+ -lpthread
+
+OBJS += Semaphore.o
+
diff --git a/Sockets/Makefile.Defines.win32-cygwin b/Sockets/Makefile.Defines.win32-cygwin
new file mode 100644
index 0000000..66ca672
--- /dev/null
+++ b/Sockets/Makefile.Defines.win32-cygwin
@@ -0,0 +1,26 @@
+CXX = g++
+
+CFLAGS += -Wall -g $(INCLUDE) -MD -D_VERSION='"$(VERSION)"'
+
+# turn off optimization if compiling with gcc 2.9.x:
+#CFLAGS += -O0
+CFLAGS += -O2 -mno-cygwin
+
+
+# uncomment depending on your operating system
+#CFLAGS += -DLINUX
+#CFLAGS += -DMACOSX
+# solaris > 8
+#CFLAGS += -DSOLARIS
+# solaris 8
+#CFLAGS += -DSOLARIS8
+# windows and/or cygwin
+CFLAGS += -D_WIN32
+# cygwin
+CFLAGS += -D__CYGWIN__
+
+
+LIBS += c:/openssl/lib/mingw/ssleay32.a \
+ c:/openssl/lib/mingw/libeay32.a \
+ -lws2_32
+
diff --git a/Sockets/Makefile.solaris9-sparc-64 b/Sockets/Makefile.solaris9-sparc-64
new file mode 100644
index 0000000..82f5ddf
--- /dev/null
+++ b/Sockets/Makefile.solaris9-sparc-64
@@ -0,0 +1,70 @@
+include Makefile.version
+
+INCLUDE =
+
+# .h files installed to $(PREFIX)/include/Sockets
+# static lib .a files installed to $(PREFIX)/lib
+PREFIX = /usr/local
+
+CXX = /opt/SUNWspro/bin/CC
+
+CFLAGS = -g $(INCLUDE) -MD -D_VERSION='"$(VERSION)"'
+CFLAGS += -features=rtti -mt
+
+# turn off optimization if compiling with gcc 2.9.x:
+#CFLAGS += -O0
+CFLAGS += -O2
+
+
+# uncomment depending on your operating system
+#CFLAGS += -DLINUX
+#CFLAGS += -DMACOSX
+# solaris > 8
+CFLAGS += -DSOLARIS
+# solaris 8
+#CFLAGS += -DSOLARIS8
+# windows and/or cygwin
+#CFLAGS += -D_WIN32
+# cygwin
+#CFLAGS += -D__CYGWIN__
+
+
+# uncomment these three lines if the library should be in its own namespace
+#CFLAGS += -DSOCKETS_NAMESPACE=sockets
+#CFLAGS += -DSOCKETS_NAMESPACE_STR='"sockets"'
+
+
+# Enable insane amounts of debug output to stdout/stderr:
+#CFLAGS += -D_DEBUG
+
+
+CPPFLAGS = $(CFLAGS)
+
+LIBS = -lSockets -lpthread -lssl -lcrypto
+
+PROGS = Sockets-config
+
+all: libSockets.a $(PROGS)
+
+Sockets-config: Sockets-config.o
+ $(CXX) -o $@ $^
+
+libSockets.a: $(OBJS)
+ ar cru $@ $(OBJS)
+ ranlib $@
+
+stressclient: stressclient.o libSockets.a
+ g++ -o $@ $^ $(LIBS)
+
+echoserver: echoserver.o libSockets.a
+ g++ -o $@ $^ $(LIBS)
+
+clean:
+ rm -f *.o *~ slask *.d $(PROGS) *.a */*~
+
+.cpp.o:
+ @echo Compiling $<
+ @$(CXX) $(CFLAGS) -c -o $@ $<
+
+-include *.d
+
diff --git a/Sockets/Makefile.version b/Sockets/Makefile.version
new file mode 100644
index 0000000..cde12a1
--- /dev/null
+++ b/Sockets/Makefile.version
@@ -0,0 +1,49 @@
+VERSION = 2.2.6
+DIFF_VERSION = 2.2.5
+
+# Sockets
+OBJS = \
+ Ajp13Socket.o \
+ AjpBaseSocket.o \
+ Base64.o \
+ Debug.o \
+ Event.o \
+ EventHandler.o \
+ EventTime.o \
+ Exception.o \
+ File.o \
+ HTTPSocket.o \
+ HttpBaseSocket.o \
+ HttpClientSocket.o \
+ HttpDebugSocket.o \
+ HttpGetSocket.o \
+ HttpPostSocket.o \
+ HttpPutSocket.o \
+ HttpRequest.o \
+ HttpResponse.o \
+ HttpTransaction.o \
+ HttpdCookies.o \
+ HttpdForm.o \
+ HttpdSocket.o \
+ IEventOwner.o \
+ Ipv4Address.o \
+ Ipv6Address.o \
+ Lock.o \
+ MemFile.o \
+ Mutex.o \
+ Parse.o \
+ RandomNumber.o \
+ ResolvServer.o \
+ ResolvSocket.o \
+ SSLInitializer.o \
+ SctpSocket.o \
+ SmtpdSocket.o \
+ Socket.o \
+ SocketHandler.o \
+ StdoutLog.o \
+ StreamSocket.o \
+ TcpSocket.o \
+ Thread.o \
+ UdpSocket.o \
+ Utility.o \
+ socket_include.o
diff --git a/Sockets/MemFile.cpp b/Sockets/MemFile.cpp
new file mode 100644
index 0000000..edbe619
--- /dev/null
+++ b/Sockets/MemFile.cpp
@@ -0,0 +1,288 @@
+/** \file MemFile.cpp
+ ** \date 2005-04-25
+ ** \author grymse@alhem.net
+**/
+/*
+Copyright (C) 2004-2007 Anders Hedstrom
+
+This library is made available under the terms of the GNU GPL.
+
+If you would like to use this library in a closed-source application,
+a separate license agreement is available. For information about
+the closed-source license agreement for the C++ sockets library,
+please visit http://www.alhem.net/Sockets/license.html and/or
+email license@alhem.net.
+
+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 _MSC_VER
+#pragma warning(disable:4786)
+#endif
+#include <stdio.h>
+#include <stdarg.h>
+
+#include "MemFile.h"
+
+
+#ifdef SOCKETS_NAMESPACE
+namespace SOCKETS_NAMESPACE {
+#endif
+
+
+std::map<std::string,MemFile::block_t *> MemFile::m_files;
+
+
+MemFile::MemFile()
+:m_temporary(true)
+,m_base(new block_t)
+,m_current_read(m_base)
+,m_current_write(m_base)
+,m_current_write_nr(0)
+,m_read_ptr(0)
+,m_write_ptr(0)
+,m_b_read_caused_eof(false)
+{
+}
+
+
+MemFile::MemFile(const std::string& path)
+:m_path(path)
+,m_temporary(false)
+,m_base(m_files[path])
+,m_current_read(NULL)
+,m_current_write(NULL)
+,m_current_write_nr(0)
+,m_read_ptr(0)
+,m_write_ptr(0)
+,m_b_read_caused_eof(false)
+{
+ if (!m_base)
+ {
+ m_base = new block_t;
+ m_files[path] = m_base;
+ }
+ m_current_read = m_base;
+ m_current_write = m_base;
+}
+
+
+MemFile::~MemFile()
+{
+ while (m_base && m_temporary)
+ {
+ block_t *p = m_base;
+ m_base = p -> next;
+ delete p;
+ }
+}
+
+
+bool MemFile::fopen(const std::string& path, const std::string& mode)
+{
+ return true;
+}
+
+
+void MemFile::fclose()
+{
+}
+
+
+size_t MemFile::fread(char *ptr, size_t size, size_t nmemb) const
+{
+ size_t p = m_read_ptr % BLOCKSIZE;
+ size_t sz = size * nmemb;
+ size_t available = m_write_ptr - m_read_ptr;
+ if (sz > available) // read beyond eof
+ {
+ sz = available;
+ m_b_read_caused_eof = true;
+ }
+ if (!sz)
+ {
+ return 0;
+ }
+ if (p + sz < BLOCKSIZE)
+ {
+ memcpy(ptr, m_current_read -> data + p, sz);
+ m_read_ptr += sz;
+ }
+ else
+ {
+ size_t sz1 = BLOCKSIZE - p;
+ size_t sz2 = sz - sz1;
+ memcpy(ptr, m_current_read -> data + p, sz1);
+ m_read_ptr += sz1;
+ while (sz2 > BLOCKSIZE)
+ {
+ if (m_current_read -> next)
+ {
+ m_current_read = m_current_read -> next;
+ memcpy(ptr + sz1, m_current_read -> data, BLOCKSIZE);
+ m_read_ptr += BLOCKSIZE;
+ sz1 += BLOCKSIZE;
+ sz2 -= BLOCKSIZE;
+ }
+ else
+ {
+ return sz1;
+ }
+ }
+ if (m_current_read -> next)
+ {
+ m_current_read = m_current_read -> next;
+ memcpy(ptr + sz1, m_current_read -> data, sz2);
+ m_read_ptr += sz2;
+ }
+ else
+ {
+ return sz1;
+ }
+ }
+ return sz;
+}
+
+
+size_t MemFile::fwrite(const char *ptr, size_t size, size_t nmemb)
+{
+ size_t p = m_write_ptr % BLOCKSIZE;
+ int nr = (int)m_write_ptr / BLOCKSIZE;
+ size_t sz = size * nmemb;
+ if (m_current_write_nr < nr)
+ {
+ block_t *next = new block_t;
+ m_current_write -> next = next;
+ m_current_write = next;
+ m_current_write_nr++;
+ }
+ if (p + sz <= BLOCKSIZE)
+ {
+ memcpy(m_current_write -> data + p, ptr, sz);
+ m_write_ptr += sz;
+ }
+ else
+ {
+ size_t sz1 = BLOCKSIZE - p; // size left
+ size_t sz2 = sz - sz1;
+ memcpy(m_current_write -> data + p, ptr, sz1);
+ m_write_ptr += sz1;
+ while (sz2 > BLOCKSIZE)
+ {
+ if (m_current_write -> next)
+ {
+ m_current_write = m_current_write -> next;
+ m_current_write_nr++;
+ }
+ else
+ {
+ block_t *next = new block_t;
+ m_current_write -> next = next;
+ m_current_write = next;
+ m_current_write_nr++;
+ }
+ memcpy(m_current_write -> data, ptr + sz1, BLOCKSIZE);
+ m_write_ptr += BLOCKSIZE;
+ sz1 += BLOCKSIZE;
+ sz2 -= BLOCKSIZE;
+ }
+ if (m_current_write -> next)
+ {
+ m_current_write = m_current_write -> next;
+ m_current_write_nr++;
+ }
+ else
+ {
+ block_t *next = new block_t;
+ m_current_write -> next = next;
+ m_current_write = next;
+ m_current_write_nr++;
+ }
+ memcpy(m_current_write -> data, ptr + sz1, sz2);
+ m_write_ptr += sz2;
+ }
+ return sz;
+}
+
+
+
+char *MemFile::fgets(char *s, int size) const
+{
+ int n = 0;
+ while (n < size - 1 && !eof())
+ {
+ char c;
+ size_t sz = fread(&c, 1, 1);
+ if (sz)
+ {
+ if (c == 10)
+ {
+ s[n] = 0;
+ return s;
+ }
+ s[n++] = c;
+ }
+ }
+ s[n] = 0;
+ return s;
+}
+
+
+void MemFile::fprintf(const char *format, ...)
+{
+ va_list ap;
+ char tmp[BLOCKSIZE];
+ va_start(ap, format);
+#ifdef _WIN32
+ vsprintf(tmp, format, ap);
+#else
+ vsnprintf(tmp, BLOCKSIZE - 1, format, ap);
+#endif
+ va_end(ap);
+ fwrite(tmp, 1, strlen(tmp));
+}
+
+
+off_t MemFile::size() const
+{
+ return (off_t)m_write_ptr;
+}
+
+
+bool MemFile::eof() const
+{
+ return m_b_read_caused_eof; //(m_read_ptr < m_write_ptr) ? false : true;
+}
+
+
+void MemFile::reset_read() const
+{
+ m_read_ptr = 0;
+ m_current_read = m_base;
+}
+
+
+void MemFile::reset_write()
+{
+ m_write_ptr = 0;
+ m_current_write = m_base;
+ m_current_write_nr = 0;
+}
+
+
+#ifdef SOCKETS_NAMESPACE
+}
+#endif
+
+
diff --git a/Sockets/MemFile.h b/Sockets/MemFile.h
new file mode 100644
index 0000000..c97b6bc
--- /dev/null
+++ b/Sockets/MemFile.h
@@ -0,0 +1,100 @@
+/** \file MemFile.h
+ ** \date 2005-04-25
+ ** \author grymse@alhem.net
+**/
+/*
+Copyright (C) 2004-2007 Anders Hedstrom
+
+This library is made available under the terms of the GNU GPL.
+
+If you would like to use this library in a closed-source application,
+a separate license agreement is available. For information about
+the closed-source license agreement for the C++ sockets library,
+please visit http://www.alhem.net/Sockets/license.html and/or
+email license@alhem.net.
+
+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.
+*/
+#ifndef _SOCKETS_MemFile_H
+#define _SOCKETS_MemFile_H
+
+#include "sockets-config.h"
+#include <map>
+#include "IFile.h"
+
+#define BLOCKSIZE 32768
+
+#ifdef SOCKETS_NAMESPACE
+namespace SOCKETS_NAMESPACE {
+#endif
+
+
+/** Implements a memory file.
+ \ingroup file */
+class MemFile : public IFile
+{
+public:
+ /** File block structure.
+ \ingroup file */
+ struct block_t {
+ block_t() : next(NULL) {}
+ struct block_t *next;
+ char data[BLOCKSIZE];
+ };
+public:
+ MemFile();
+ MemFile(const std::string& path);
+ ~MemFile();
+
+ bool fopen(const std::string& path, const std::string& mode);
+ void fclose();
+
+ size_t fread(char *ptr, size_t size, size_t nmemb) const;
+ size_t fwrite(const char *ptr, size_t size, size_t nmemb);
+
+ char *fgets(char *s, int size) const;
+ void fprintf(const char *format, ...);
+
+ off_t size() const;
+ bool eof() const;
+
+ void reset_read() const;
+ void reset_write();
+
+private:
+ MemFile(const MemFile& ) {} // copy constructor
+ MemFile& operator=(const MemFile& ) { return *this; } // assignment operator
+
+static std::map<std::string,block_t *> m_files;
+ std::string m_path;
+ bool m_temporary;
+ block_t *m_base;
+ mutable block_t *m_current_read;
+ block_t *m_current_write;
+ int m_current_write_nr;
+ mutable size_t m_read_ptr;
+ size_t m_write_ptr;
+ mutable bool m_b_read_caused_eof;
+};
+
+
+
+
+#ifdef SOCKETS_NAMESPACE
+}
+#endif
+
+#endif // _SOCKETS_MemFile_H
+
diff --git a/Sockets/Mutex.cpp b/Sockets/Mutex.cpp
new file mode 100644
index 0000000..4b0e681
--- /dev/null
+++ b/Sockets/Mutex.cpp
@@ -0,0 +1,81 @@
+/** \file Mutex.cpp
+ ** \date 2004-10-30
+ ** \author grymse@alhem.net
+**/
+/*
+Copyright (C) 2004-2007 Anders Hedstrom
+
+This library is made available under the terms of the GNU GPL.
+
+If you would like to use this library in a closed-source application,
+a separate license agreement is available. For information about
+the closed-source license agreement for the C++ sockets library,
+please visit http://www.alhem.net/Sockets/license.html and/or
+email license@alhem.net.
+
+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.
+*/
+#include "Mutex.h"
+
+#ifdef SOCKETS_NAMESPACE
+namespace SOCKETS_NAMESPACE {
+#endif
+
+
+Mutex::Mutex()
+{
+#ifdef _WIN32
+ m_mutex = ::CreateMutex(NULL, FALSE, NULL);
+#else
+ pthread_mutex_init(&m_mutex, NULL);
+#endif
+}
+
+
+Mutex::~Mutex()
+{
+#ifdef _WIN32
+ ::CloseHandle(m_mutex);
+#else
+ pthread_mutex_destroy(&m_mutex);
+#endif
+}
+
+
+void Mutex::Lock()
+{
+#ifdef _WIN32
+ DWORD d = WaitForSingleObject(m_mutex, INFINITE);
+ /// \todo check 'd' for result
+#else
+ pthread_mutex_lock(&m_mutex);
+#endif
+}
+
+
+void Mutex::Unlock()
+{
+#ifdef _WIN32
+ ::ReleaseMutex(m_mutex);
+#else
+ pthread_mutex_unlock(&m_mutex);
+#endif
+}
+
+
+#ifdef SOCKETS_NAMESPACE
+}
+#endif
+
diff --git a/Sockets/Mutex.h b/Sockets/Mutex.h
new file mode 100644
index 0000000..1de2776
--- /dev/null
+++ b/Sockets/Mutex.h
@@ -0,0 +1,68 @@
+/** \file Mutex.h
+ ** \date 2004-10-30
+ ** \author grymse@alhem.net
+**/
+/*
+Copyright (C) 2004-2007 Anders Hedstrom
+
+This library is made available under the terms of the GNU GPL.
+
+If you would like to use this library in a closed-source application,
+a separate license agreement is available. For information about
+the closed-source license agreement for the C++ sockets library,
+please visit http://www.alhem.net/Sockets/license.html and/or
+email license@alhem.net.
+
+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.
+*/
+#ifndef _SOCKETS_Mutex_H
+#define _SOCKETS_Mutex_H
+
+#include "sockets-config.h"
+#ifndef _WIN32
+#include <pthread.h>
+#else
+#include <windows.h>
+#endif
+
+#ifdef SOCKETS_NAMESPACE
+namespace SOCKETS_NAMESPACE {
+#endif
+
+/** Mutex container class, used by Lock.
+ \ingroup threading */
+class Mutex
+{
+ friend class Lock;
+public:
+ Mutex();
+ ~Mutex();
+
+ void Lock();
+ void Unlock();
+private:
+#ifdef _WIN32
+ HANDLE m_mutex;
+#else
+ pthread_mutex_t m_mutex;
+#endif
+};
+
+
+#ifdef SOCKETS_NAMESPACE
+}
+#endif
+#endif // _SOCKETS_Mutex_H
+
diff --git a/Sockets/OSX.zip b/Sockets/OSX.zip
new file mode 100755
index 0000000..e4046a4
--- /dev/null
+++ b/Sockets/OSX.zip
Binary files differ
diff --git a/Sockets/Parse.cpp b/Sockets/Parse.cpp
new file mode 100644
index 0000000..6de56f0
--- /dev/null
+++ b/Sockets/Parse.cpp
@@ -0,0 +1,321 @@
+/** \file Parse.cpp - parse a string
+ **
+ ** Written: 1999-Feb-10 grymse@alhem.net
+ **/
+
+/*
+Copyright (C) 1999-2007 Anders Hedstrom
+
+This library is made available under the terms of the GNU GPL.
+
+If you would like to use this library in a closed-source application,
+a separate license agreement is available. For information about
+the closed-source license agreement for the C++ sockets library,
+please visit http://www.alhem.net/Sockets/license.html and/or
+email license@alhem.net.
+
+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.
+*/
+#include <stdlib.h>
+#include <string.h>
+
+#include "Parse.h"
+
+
+#ifdef SOCKETS_NAMESPACE
+namespace SOCKETS_NAMESPACE {
+#endif
+
+
+/* implementation of class Parse */
+
+Parse::Parse()
+:pa_the_str("")
+,pa_splits("")
+,pa_ord("")
+,pa_the_ptr(0)
+,pa_breakchar(0)
+,pa_enable(0)
+,pa_disable(0)
+,pa_nospace(0)
+,pa_quote(false)
+{
+}
+
+Parse::Parse(const std::string&s)
+:pa_the_str(s)
+,pa_splits("")
+,pa_ord("")
+,pa_the_ptr(0)
+,pa_breakchar(0)
+,pa_enable(0)
+,pa_disable(0)
+,pa_nospace(0)
+,pa_quote(false)
+{
+}
+
+Parse::Parse(const std::string&s,const std::string&sp)
+:pa_the_str(s)
+,pa_splits(sp)
+,pa_ord("")
+,pa_the_ptr(0)
+,pa_breakchar(0)
+,pa_enable(0)
+,pa_disable(0)
+,pa_nospace(0)
+,pa_quote(false)
+{
+}
+
+Parse::Parse(const std::string&s,const std::string&sp,short nospace)
+:pa_the_str(s)
+,pa_splits(sp)
+,pa_ord("")
+,pa_the_ptr(0)
+,pa_breakchar(0)
+,pa_enable(0)
+,pa_disable(0)
+,pa_nospace(1)
+,pa_quote(false)
+{
+}
+
+
+Parse::~Parse()
+{
+}
+
+#define C ((pa_the_ptr<pa_the_str.size()) ? pa_the_str[pa_the_ptr] : 0)
+
+short Parse::issplit(const char c)
+{
+ for (size_t i = 0; i < pa_splits.size(); i++)
+ if (pa_splits[i] == c)
+ return 1;
+ return 0;
+}
+
+void Parse::getsplit()
+{
+ size_t x;
+
+ if (C == '=')
+ {
+ x = pa_the_ptr++;
+ } else
+ {
+ while (C && (issplit(C)))
+ pa_the_ptr++;
+ x = pa_the_ptr;
+ while (C && !issplit(C) && C != '=')
+ pa_the_ptr++;
+ }
+ if (x == pa_the_ptr && C == '=')
+ pa_the_ptr++;
+ pa_ord = (x < pa_the_str.size()) ? pa_the_str.substr(x,pa_the_ptr - x) : "";
+}
+
+std::string Parse::getword()
+{
+ size_t x;
+ int disabled = 0;
+ int quote = 0;
+ int rem = 0;
+
+ if (pa_nospace)
+ {
+ while (C && issplit(C))
+ pa_the_ptr++;
+ x = pa_the_ptr;
+ while (C && !issplit(C) && (C != pa_breakchar || !pa_breakchar || disabled))
+ {
+ if (pa_breakchar && C == pa_disable)
+ disabled = 1;
+ if (pa_breakchar && C == pa_enable)
+ disabled = 0;
+ if (pa_quote && C == '"')
+ quote = 1;
+ pa_the_ptr++;
+ while (quote && C && C != '"')
+ {
+ pa_the_ptr++;
+ }
+ if (pa_quote && C == '"')
+ {
+ pa_the_ptr++;
+ }
+ quote = 0;
+ }
+ } else
+ {
+ if (C == pa_breakchar && pa_breakchar)
+ {
+ x = pa_the_ptr++;
+ rem = 1;
+ } else
+ {
+ while (C && (C == ' ' || C == 9 || C == 13 || C == 10 || issplit(C)))
+ pa_the_ptr++;
+ x = pa_the_ptr;
+ while (C && C != ' ' && C != 9 && C != 13 && C != 10 && !issplit(C) &&
+ (C != pa_breakchar || !pa_breakchar || disabled))
+ {
+ if (pa_breakchar && C == pa_disable)
+ disabled = 1;
+ if (pa_breakchar && C == pa_enable)
+ disabled = 0;
+ if (pa_quote && C == '"')
+ {
+ quote = 1;
+ pa_the_ptr++;
+ while (quote && C && C != '"')
+ {
+ pa_the_ptr++;
+ }
+ if (pa_quote && C == '"')
+ {
+ pa_the_ptr++;
+ }
+ }
+ else
+ pa_the_ptr++;
+ quote = 0;
+ }
+ pa_the_ptr++;
+ rem = 1;
+ }
+ if (x == pa_the_ptr && C == pa_breakchar && pa_breakchar)
+ pa_the_ptr++;
+ }
+ if (x < pa_the_str.size())
+ {
+ pa_ord = pa_the_str.substr(x,pa_the_ptr - x - rem);
+ }
+ else
+ {
+ pa_ord = "";
+ }
+ return pa_ord;
+}
+
+void Parse::getword(std::string&s)
+{
+ s = Parse::getword();
+}
+
+void Parse::getsplit(std::string&s)
+{
+ Parse::getsplit();
+ s = pa_ord;
+}
+
+void Parse::getword(std::string&s,std::string&fill,int l)
+{
+ Parse::getword();
+ s = "";
+ while (s.size() + pa_ord.size() < (size_t)l)
+ s += fill;
+ s += pa_ord;
+}
+
+std::string Parse::getrest()
+{
+ std::string s;
+ while (C && (C == ' ' || C == 9 || issplit(C)))
+ pa_the_ptr++;
+ s = (pa_the_ptr < pa_the_str.size()) ? pa_the_str.substr(pa_the_ptr) : "";
+ return s;
+}
+
+void Parse::getrest(std::string&s)
+{
+ while (C && (C == ' ' || C == 9 || issplit(C)))
+ pa_the_ptr++;
+ s = (pa_the_ptr < pa_the_str.size()) ? pa_the_str.substr(pa_the_ptr) : "";
+}
+
+long Parse::getvalue()
+{
+ Parse::getword();
+ return atol(pa_ord.c_str());
+}
+
+void Parse::setbreak(const char c)
+{
+ pa_breakchar = c;
+}
+
+int Parse::getwordlen()
+{
+ size_t x,y = pa_the_ptr,len;
+
+ if (C == pa_breakchar && pa_breakchar)
+ {
+ x = pa_the_ptr++;
+ } else
+ {
+ while (C && (C == ' ' || C == 9 || C == 13 || C == 10 || issplit(C)))
+ pa_the_ptr++;
+ x = pa_the_ptr;
+ while (C && C != ' ' && C != 9 && C != 13 && C != 10 && !issplit(C) && (C != pa_breakchar || !pa_breakchar))
+ pa_the_ptr++;
+ }
+ if (x == pa_the_ptr && C == pa_breakchar && pa_breakchar)
+ pa_the_ptr++;
+ len = pa_the_ptr - x;
+ pa_the_ptr = y;
+ return (int)len;
+}
+
+int Parse::getrestlen()
+{
+ size_t y = pa_the_ptr;
+ size_t len;
+
+ while (C && (C == ' ' || C == 9 || issplit(C)))
+ pa_the_ptr++;
+ len = strlen(pa_the_str.c_str() + pa_the_ptr);
+ pa_the_ptr = y;
+ return (int)len;
+}
+
+void Parse::getline()
+{
+ size_t x;
+
+ x = pa_the_ptr;
+ while (C && C != 13 && C != 10)
+ pa_the_ptr++;
+ pa_ord = (x < pa_the_str.size()) ? pa_the_str.substr(x,pa_the_ptr - x) : "";
+ if (C == 13)
+ pa_the_ptr++;
+ if (C == 10)
+ pa_the_ptr++;
+}
+
+void Parse::getline(std::string&s)
+{
+ getline();
+ s = pa_ord;
+}
+
+/* end of implementation of class Parse */
+/***************************************************/
+#ifdef SOCKETS_NAMESPACE
+}
+#endif
+
+
diff --git a/Sockets/Parse.h b/Sockets/Parse.h
new file mode 100644
index 0000000..6961f3b
--- /dev/null
+++ b/Sockets/Parse.h
@@ -0,0 +1,101 @@
+/** \file Parse.h - parse a string
+ **
+ ** Written: 1999-Feb-10 grymse@alhem.net
+ **/
+
+/*
+Copyright (C) 1999-2007 Anders Hedstrom
+
+This library is made available under the terms of the GNU GPL.
+
+If you would like to use this library in a closed-source application,
+a separate license agreement is available. For information about
+the closed-source license agreement for the C++ sockets library,
+please visit http://www.alhem.net/Sockets/license.html and/or
+email license@alhem.net.
+
+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.
+*/
+
+#ifndef _SOCKETS_Parse_H
+#define _SOCKETS_Parse_H
+
+#include "sockets-config.h"
+#ifdef _MSC_VER
+#pragma warning(disable:4514)
+#endif
+
+#include <string>
+
+#ifdef SOCKETS_NAMESPACE
+namespace SOCKETS_NAMESPACE {
+#endif
+
+
+/***************************************************/
+/* interface of class Parse */
+
+/** Splits a string whatever way you want.
+ \ingroup util */
+class Parse
+{
+public:
+ Parse();
+ Parse(const std::string&);
+ Parse(const std::string&,const std::string&);
+ Parse(const std::string&,const std::string&,short);
+ ~Parse();
+ short issplit(const char);
+ void getsplit();
+ void getsplit(std::string&);
+ std::string getword();
+ void getword(std::string&);
+ void getword(std::string&,std::string&,int);
+ std::string getrest();
+ void getrest(std::string&);
+ long getvalue();
+ void setbreak(const char);
+ int getwordlen();
+ int getrestlen();
+ void enablebreak(const char c) {
+ pa_enable = c;
+ }
+ void disablebreak(const char c) {
+ pa_disable = c;
+ }
+ void getline();
+ void getline(std::string&);
+ size_t getptr() { return pa_the_ptr; }
+ void EnableQuote(bool b) { pa_quote = b; }
+
+private:
+ std::string pa_the_str;
+ std::string pa_splits;
+ std::string pa_ord;
+ size_t pa_the_ptr;
+ char pa_breakchar;
+ char pa_enable;
+ char pa_disable;
+ short pa_nospace;
+ bool pa_quote;
+};
+
+
+#ifdef SOCKETS_NAMESPACE
+}
+#endif
+
+#endif // _SOCKETS_Parse_H
+
diff --git a/Sockets/Project.net/Sockets/Sockets.sln b/Sockets/Project.net/Sockets/Sockets.sln
new file mode 100644
index 0000000..9204f43
--- /dev/null
+++ b/Sockets/Project.net/Sockets/Sockets.sln
@@ -0,0 +1,30 @@
+Microsoft Visual Studio Solution File, Format Version 8.00
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Sockets", "Sockets.vcproj", "{1EC00E34-E016-4EB4-BF7D-B5B7E101AE57}"
+ ProjectSection(ProjectDependencies) = postProject
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Test", "..\Test\Test.vcproj", "{D73A0C4B-7554-4A86-A452-5A12675925A0}"
+ ProjectSection(ProjectDependencies) = postProject
+ {1EC00E34-E016-4EB4-BF7D-B5B7E101AE57} = {1EC00E34-E016-4EB4-BF7D-B5B7E101AE57}
+ EndProjectSection
+EndProject
+Global
+ GlobalSection(SolutionConfiguration) = preSolution
+ Debug = Debug
+ Release = Release
+ EndGlobalSection
+ GlobalSection(ProjectConfiguration) = postSolution
+ {1EC00E34-E016-4EB4-BF7D-B5B7E101AE57}.Debug.ActiveCfg = Debug|Win32
+ {1EC00E34-E016-4EB4-BF7D-B5B7E101AE57}.Debug.Build.0 = Debug|Win32
+ {1EC00E34-E016-4EB4-BF7D-B5B7E101AE57}.Release.ActiveCfg = Release|Win32
+ {1EC00E34-E016-4EB4-BF7D-B5B7E101AE57}.Release.Build.0 = Release|Win32
+ {D73A0C4B-7554-4A86-A452-5A12675925A0}.Debug.ActiveCfg = Debug|Win32
+ {D73A0C4B-7554-4A86-A452-5A12675925A0}.Debug.Build.0 = Debug|Win32
+ {D73A0C4B-7554-4A86-A452-5A12675925A0}.Release.ActiveCfg = Release|Win32
+ {D73A0C4B-7554-4A86-A452-5A12675925A0}.Release.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ EndGlobalSection
+ GlobalSection(ExtensibilityAddIns) = postSolution
+ EndGlobalSection
+EndGlobal
diff --git a/Sockets/Project.net/Sockets/Sockets.vcproj b/Sockets/Project.net/Sockets/Sockets.vcproj
new file mode 100644
index 0000000..4e008d6
--- /dev/null
+++ b/Sockets/Project.net/Sockets/Sockets.vcproj
@@ -0,0 +1,452 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="Sockets"
+ ProjectGUID="{1EC00E34-E016-4EB4-BF7D-B5B7E101AE57}"
+ Keyword="Win32Proj">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="..\lib\D"
+ IntermediateDirectory="Debug"
+ ConfigurationType="4"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="C:\OpenSSL\include"
+ PreprocessorDefinitions="WIN32;_DEBUG;_LIB"
+ MinimalRebuild="TRUE"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ EnableFunctionLevelLinking="FALSE"
+ RuntimeTypeInfo="TRUE"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="TRUE"
+ DebugInformationFormat="4"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="$(OutDir)/Sockets.lib"
+ AdditionalLibraryDirectories=""/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="xcopy ..\..\*.h ..\Include /I /Y"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="..\lib\R"
+ IntermediateDirectory="Release"
+ ConfigurationType="4"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="C:\OpenSSL\include"
+ PreprocessorDefinitions="WIN32;NDEBUG;_LIB"
+ RuntimeLibrary="0"
+ RuntimeTypeInfo="TRUE"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="TRUE"
+ DebugInformationFormat="3"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="$(OutDir)/Sockets.lib"
+ AdditionalLibraryDirectories=""/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="xcopy ..\..\*.h ..\Include /I /Y"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
+ <File
+ RelativePath="..\..\Exception.cpp">
+ </File>
+ <File
+ RelativePath="..\..\socket_include.cpp">
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">
+ <File
+ RelativePath="..\..\Exception.h">
+ </File>
+ <File
+ RelativePath="..\..\socket_include.h">
+ </File>
+ <File
+ RelativePath="..\..\sockets-config.h">
+ </File>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}">
+ </Filter>
+ <Filter
+ Name="Utilities"
+ Filter="">
+ <File
+ RelativePath="..\..\Base64.cpp">
+ </File>
+ <File
+ RelativePath="..\..\Base64.h">
+ </File>
+ <File
+ RelativePath="..\..\Parse.cpp">
+ </File>
+ <File
+ RelativePath="..\..\Parse.h">
+ </File>
+ <File
+ RelativePath="..\..\RandomNumber.cpp">
+ </File>
+ <File
+ RelativePath="..\..\RandomNumber.h">
+ </File>
+ <File
+ RelativePath="..\..\Utility.cpp">
+ </File>
+ <File
+ RelativePath="..\..\Utility.h">
+ </File>
+ </Filter>
+ <Filter
+ Name="Internal"
+ Filter="">
+ <File
+ RelativePath="..\..\SSLInitializer.cpp">
+ </File>
+ <File
+ RelativePath="..\..\SSLInitializer.h">
+ </File>
+ </Filter>
+ <Filter
+ Name="Webserver framework"
+ Filter="">
+ <File
+ RelativePath="..\..\ajp13.h">
+ </File>
+ <File
+ RelativePath="..\..\Ajp13Socket.cpp">
+ </File>
+ <File
+ RelativePath="..\..\Ajp13Socket.h">
+ </File>
+ <File
+ RelativePath="..\..\AjpBaseSocket.cpp">
+ </File>
+ <File
+ RelativePath="..\..\AjpBaseSocket.h">
+ </File>
+ <File
+ RelativePath="..\..\HttpBaseSocket.cpp">
+ </File>
+ <File
+ RelativePath="..\..\HttpBaseSocket.h">
+ </File>
+ <File
+ RelativePath="..\..\HttpdCookies.cpp">
+ </File>
+ <File
+ RelativePath="..\..\HttpdCookies.h">
+ </File>
+ <File
+ RelativePath="..\..\HttpdForm.cpp">
+ </File>
+ <File
+ RelativePath="..\..\HttpdForm.h">
+ </File>
+ <File
+ RelativePath="..\..\HttpdSocket.cpp">
+ </File>
+ <File
+ RelativePath="..\..\HttpdSocket.h">
+ </File>
+ <File
+ RelativePath="..\..\HttpRequest.cpp">
+ </File>
+ <File
+ RelativePath="..\..\HttpRequest.h">
+ </File>
+ <File
+ RelativePath="..\..\HttpResponse.cpp">
+ </File>
+ <File
+ RelativePath="..\..\HttpResponse.h">
+ </File>
+ <File
+ RelativePath="..\..\HttpTransaction.cpp">
+ </File>
+ <File
+ RelativePath="..\..\HttpTransaction.h">
+ </File>
+ <File
+ RelativePath="..\..\IHttpServer.h">
+ </File>
+ </Filter>
+ <Filter
+ Name="HTTP Sockets"
+ Filter="">
+ <File
+ RelativePath="..\..\HttpClientSocket.cpp">
+ </File>
+ <File
+ RelativePath="..\..\HttpClientSocket.h">
+ </File>
+ <File
+ RelativePath="..\..\HttpDebugSocket.cpp">
+ </File>
+ <File
+ RelativePath="..\..\HttpDebugSocket.h">
+ </File>
+ <File
+ RelativePath="..\..\HttpGetSocket.cpp">
+ </File>
+ <File
+ RelativePath="..\..\HttpGetSocket.h">
+ </File>
+ <File
+ RelativePath="..\..\HttpPostSocket.cpp">
+ </File>
+ <File
+ RelativePath="..\..\HttpPostSocket.h">
+ </File>
+ <File
+ RelativePath="..\..\HttpPutSocket.cpp">
+ </File>
+ <File
+ RelativePath="..\..\HttpPutSocket.h">
+ </File>
+ <File
+ RelativePath="..\..\HTTPSocket.cpp">
+ </File>
+ <File
+ RelativePath="..\..\HTTPSocket.h">
+ </File>
+ </Filter>
+ <Filter
+ Name="File handling"
+ Filter="">
+ <File
+ RelativePath="..\..\File.cpp">
+ </File>
+ <File
+ RelativePath="..\..\File.h">
+ </File>
+ <File
+ RelativePath="..\..\IFile.h">
+ </File>
+ <File
+ RelativePath="..\..\MemFile.cpp">
+ </File>
+ <File
+ RelativePath="..\..\MemFile.h">
+ </File>
+ </Filter>
+ <Filter
+ Name="Asyncronous DNS"
+ Filter="">
+ <File
+ RelativePath="..\..\ResolvServer.cpp">
+ </File>
+ <File
+ RelativePath="..\..\ResolvServer.h">
+ </File>
+ <File
+ RelativePath="..\..\ResolvSocket.cpp">
+ </File>
+ <File
+ RelativePath="..\..\ResolvSocket.h">
+ </File>
+ </Filter>
+ <Filter
+ Name="Basic Sockets"
+ Filter="">
+ <File
+ RelativePath="..\..\Ipv4Address.cpp">
+ </File>
+ <File
+ RelativePath="..\..\Ipv4Address.h">
+ </File>
+ <File
+ RelativePath="..\..\Ipv6Address.cpp">
+ </File>
+ <File
+ RelativePath="..\..\Ipv6Address.h">
+ </File>
+ <File
+ RelativePath="..\..\ISocketHandler.h">
+ </File>
+ <File
+ RelativePath="..\..\ListenSocket.h">
+ </File>
+ <File
+ RelativePath="..\..\SctpSocket.cpp">
+ </File>
+ <File
+ RelativePath="..\..\SctpSocket.h">
+ </File>
+ <File
+ RelativePath="..\..\Socket.cpp">
+ </File>
+ <File
+ RelativePath="..\..\Socket.h">
+ </File>
+ <File
+ RelativePath="..\..\SocketAddress.h">
+ </File>
+ <File
+ RelativePath="..\..\SocketHandler.cpp">
+ </File>
+ <File
+ RelativePath="..\..\SocketHandler.h">
+ </File>
+ <File
+ RelativePath="..\..\StreamSocket.cpp">
+ </File>
+ <File
+ RelativePath="..\..\StreamSocket.h">
+ </File>
+ <File
+ RelativePath="..\..\TcpSocket.cpp">
+ </File>
+ <File
+ RelativePath="..\..\TcpSocket.h">
+ </File>
+ <File
+ RelativePath="..\..\UdpSocket.cpp">
+ </File>
+ <File
+ RelativePath="..\..\UdpSocket.h">
+ </File>
+ </Filter>
+ <Filter
+ Name="Log help classes"
+ Filter="">
+ <File
+ RelativePath="..\..\StdLog.h">
+ </File>
+ <File
+ RelativePath="..\..\StdoutLog.cpp">
+ </File>
+ <File
+ RelativePath="..\..\StdoutLog.h">
+ </File>
+ </Filter>
+ <Filter
+ Name="Threading"
+ Filter="">
+ <File
+ RelativePath="..\..\Lock.cpp">
+ </File>
+ <File
+ RelativePath="..\..\Lock.h">
+ </File>
+ <File
+ RelativePath="..\..\Mutex.cpp">
+ </File>
+ <File
+ RelativePath="..\..\Mutex.h">
+ </File>
+ <File
+ RelativePath="..\..\Thread.cpp">
+ </File>
+ <File
+ RelativePath="..\..\Thread.h">
+ </File>
+ </Filter>
+ <Filter
+ Name="Timer Events"
+ Filter="">
+ <File
+ RelativePath="..\..\Event.cpp">
+ </File>
+ <File
+ RelativePath="..\..\Event.h">
+ </File>
+ <File
+ RelativePath="..\..\EventHandler.cpp">
+ </File>
+ <File
+ RelativePath="..\..\EventHandler.h">
+ </File>
+ <File
+ RelativePath="..\..\EventTime.cpp">
+ </File>
+ <File
+ RelativePath="..\..\EventTime.h">
+ </File>
+ <File
+ RelativePath="..\..\IEventHandler.h">
+ </File>
+ <File
+ RelativePath="..\..\IEventOwner.cpp">
+ </File>
+ <File
+ RelativePath="..\..\IEventOwner.h">
+ </File>
+ </Filter>
+ <Filter
+ Name="SMTP"
+ Filter="">
+ <File
+ RelativePath="..\..\SmtpdSocket.cpp">
+ </File>
+ <File
+ RelativePath="..\..\SmtpdSocket.h">
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/Sockets/Project.net/Test/Test.vcproj b/Sockets/Project.net/Test/Test.vcproj
new file mode 100644
index 0000000..fa24b0e
--- /dev/null
+++ b/Sockets/Project.net/Test/Test.vcproj
@@ -0,0 +1,140 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="Test"
+ ProjectGUID="{D73A0C4B-7554-4A86-A452-5A12675925A0}"
+ Keyword="Win32Proj">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="..\bin\d"
+ IntermediateDirectory="Debug"
+ ConfigurationType="1"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="C:\OpenSSL\include;..\Include"
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;HAVE_OPENSSL"
+ MinimalRebuild="TRUE"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ RuntimeTypeInfo="TRUE"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="TRUE"
+ DebugInformationFormat="4"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="Sockets.lib libeay32mt.lib ssleay32mt.lib"
+ OutputFile="$(OutDir)/Test.exe"
+ LinkIncremental="2"
+ AdditionalLibraryDirectories="C:\OpenSSL\lib\VC\static;..\lib\D"
+ GenerateDebugInformation="TRUE"
+ ProgramDatabaseFile="$(OutDir)/Test.pdb"
+ SubSystem="1"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="..\bin\R"
+ IntermediateDirectory="Release"
+ ConfigurationType="1"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="C:\OpenSSL\include;..\Include"
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;HAVE_OPENSSL"
+ RuntimeLibrary="0"
+ RuntimeTypeInfo="TRUE"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="TRUE"
+ DebugInformationFormat="3"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="Sockets.lib libeay32mt.lib ssleay32mt.lib"
+ OutputFile="$(OutDir)/Test.exe"
+ LinkIncremental="1"
+ AdditionalLibraryDirectories="C:\OpenSSL\lib\VC\static;..\lib\R"
+ GenerateDebugInformation="TRUE"
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
+ <File
+ RelativePath="..\..\tests\sockets_test.cpp">
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}">
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/Sockets/Project/Sockets.dsp b/Sockets/Project/Sockets.dsp
new file mode 100644
index 0000000..b9bda66
--- /dev/null
+++ b/Sockets/Project/Sockets.dsp
@@ -0,0 +1,526 @@
+# Microsoft Developer Studio Project File - Name="Sockets" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=Sockets - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "Sockets.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "Sockets.mak" CFG="Sockets - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "Sockets - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "Sockets - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "Sockets - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "..\..\lib\R"
+# PROP Intermediate_Dir "R"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GR /GX /O2 /I "c:\openssl\include" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo
+# Begin Special Build Tool
+SOURCE="$(InputPath)"
+PostBuild_Cmds=xcopy ..\*.h Include /I /Y
+# End Special Build Tool
+
+!ELSEIF "$(CFG)" == "Sockets - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "..\..\lib\D"
+# PROP Intermediate_Dir "D"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# ADD CPP /nologo /MTd /W3 /Gm /GR /GX /ZI /Od /I "c:\openssl\include" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /FD /GZ /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo
+# Begin Special Build Tool
+SOURCE="$(InputPath)"
+PostBuild_Cmds=xcopy ..\*.h Include /I /Y
+# End Special Build Tool
+
+!ENDIF
+
+# Begin Target
+
+# Name "Sockets - Win32 Release"
+# Name "Sockets - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\Exception.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\socket_include.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\Exception.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\socket_include.h
+# End Source File
+# Begin Source File
+
+SOURCE="..\sockets-config.h"
+# End Source File
+# End Group
+# Begin Group "Utilities"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\Base64.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Base64.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\Parse.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Parse.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\RandomNumber.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\RandomNumber.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\Utility.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Utility.h
+# End Source File
+# End Group
+# Begin Group "Internal"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\SSLInitializer.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\SSLInitializer.h
+# End Source File
+# End Group
+# Begin Group "Webserver framework"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\HttpdCookies.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\HttpdCookies.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\HttpdForm.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\HttpdForm.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\HttpdSocket.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\HttpdSocket.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\Ajp13Socket.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Ajp13Socket.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\AjpBaseSocket.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\AjpBaseSocket.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\HttpBaseSocket.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\HttpBaseSocket.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\HttpTransaction.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\HttpTransaction.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\HttpRequest.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\HttpRequest.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\HttpResponse.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\HttpResponse.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\ajp13.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\IHttpServer.h
+# End Source File
+# End Group
+# Begin Group "HTTP Sockets"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\HttpClientSocket.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\HttpClientSocket.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\HttpDebugSocket.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\HttpDebugSocket.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\HttpGetSocket.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\HttpGetSocket.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\HttpPostSocket.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\HttpPostSocket.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\HttpPutSocket.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\HttpPutSocket.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\HTTPSocket.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\HTTPSocket.h
+# End Source File
+# End Group
+# Begin Group "File handling"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\File.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\File.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\IFile.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\MemFile.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\MemFile.h
+# End Source File
+# End Group
+# Begin Group "Asynchronous DNS"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\ResolvServer.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\ResolvServer.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\ResolvSocket.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\ResolvSocket.h
+# End Source File
+# End Group
+# Begin Group "Basic Sockets"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\Ipv4Address.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Ipv4Address.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\Ipv6Address.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Ipv6Address.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\ISocketHandler.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\ListenSocket.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\SctpSocket.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\SctpSocket.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\Socket.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Socket.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\SocketAddress.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\SocketHandler.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\SocketHandler.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\StreamSocket.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\StreamSocket.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\TcpSocket.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\TcpSocket.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\UdpSocket.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\UdpSocket.h
+# End Source File
+# End Group
+# Begin Group "Log help classes"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\StdLog.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\StdoutLog.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\StdoutLog.h
+# End Source File
+# End Group
+# Begin Group "Threading"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\Lock.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Lock.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\Mutex.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Mutex.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\Thread.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Thread.h
+# End Source File
+# End Group
+# Begin Group "Timer Events"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\Event.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Event.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\EventHandler.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\EventHandler.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\EventTime.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\EventTime.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\IEventHandler.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\IEventOwner.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\IEventOwner.h
+# End Source File
+# End Group
+# Begin Group "SMTP"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\SmtpdSocket.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\SmtpdSocket.h
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/Sockets/Project/Sockets.dsw b/Sockets/Project/Sockets.dsw
new file mode 100644
index 0000000..3a7694c
--- /dev/null
+++ b/Sockets/Project/Sockets.dsw
@@ -0,0 +1,68 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "Sockets"=.\Sockets.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "Test"=.\Test.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name Sockets
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "echoserver"=.\echoserver.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "stressclient"=.\stressclient.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/Sockets/Project/Test.dsp b/Sockets/Project/Test.dsp
new file mode 100644
index 0000000..74efc10
--- /dev/null
+++ b/Sockets/Project/Test.dsp
@@ -0,0 +1,102 @@
+# Microsoft Developer Studio Project File - Name="Test" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=Test - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "Test.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "Test.mak" CFG="Test - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "Test - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "Test - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "Test - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "bin\R"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GR /GX /O2 /I "Include" /I "c:\openssl\include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /D "HAVE_OPENSSL" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib Sockets.lib libeay32md.lib ssleay32md.lib /nologo /subsystem:console /machine:I386 /libpath:"..\..\lib\R" /libpath:"c:\openssl\lib\vc"
+
+!ELSEIF "$(CFG)" == "Test - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "bin\D"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /MTd /W3 /Gm /GR /GX /ZI /Od /I "Include" /I "c:\openssl\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "HAVE_OPENSSL" /YX /FD /GZ /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib Sockets.lib libeay32md.lib ssleay32md.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\..\lib\D" /libpath:"c:\openssl\lib\vc"
+
+!ENDIF
+
+# Begin Target
+
+# Name "Test - Win32 Release"
+# Name "Test - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\tests\sockets_test.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/Sockets/Project/echoserver.dsp b/Sockets/Project/echoserver.dsp
new file mode 100644
index 0000000..d848565
--- /dev/null
+++ b/Sockets/Project/echoserver.dsp
@@ -0,0 +1,100 @@
+# Microsoft Developer Studio Project File - Name="echoserver" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=echoserver - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "echoserver.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "echoserver.mak" CFG="echoserver - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "echoserver - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "echoserver - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "echoserver - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "echoserver___Win32_Release"
+# PROP BASE Intermediate_Dir "echoserver___Win32_Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "R"
+# PROP Intermediate_Dir "echoserver___Win32_Release"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GR /GX /O2 /I "..\..\Sockets" /I "c:\openssl\include" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "HAVE_OPENSSL" /YX /FD /c
+# ADD BASE RSC /l 0x41d /d "NDEBUG"
+# ADD RSC /l 0x41d /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib Sockets.lib ssleay32md.lib libeay32md.lib /nologo /subsystem:console /machine:I386 /libpath:"\openssl\lib\vc" /libpath:"..\..\lib\r"
+
+!ELSEIF "$(CFG)" == "echoserver - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "echoserver___Win32_Debug"
+# PROP BASE Intermediate_Dir "echoserver___Win32_Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "D"
+# PROP Intermediate_Dir "echoserver___Win32_Debug"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /MTd /W3 /Gm /GR /GX /ZI /Od /I "..\..\Sockets" /I "c:\openssl\include" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "HAVE_OPENSSL" /YX /FD /GZ /c
+# ADD BASE RSC /l 0x41d /d "_DEBUG"
+# ADD RSC /l 0x41d /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib Sockets.lib ssleay32md.lib libeay32md.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"\openssl\lib\vc" /libpath:"..\..\lib\d"
+
+!ENDIF
+
+# Begin Target
+
+# Name "echoserver - Win32 Release"
+# Name "echoserver - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\tests\echoserver.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/Sockets/Project/stressclient.dsp b/Sockets/Project/stressclient.dsp
new file mode 100644
index 0000000..34eb22d
--- /dev/null
+++ b/Sockets/Project/stressclient.dsp
@@ -0,0 +1,100 @@
+# Microsoft Developer Studio Project File - Name="stressclient" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=stressclient - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "stressclient.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "stressclient.mak" CFG="stressclient - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "stressclient - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "stressclient - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "stressclient - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "R"
+# PROP Intermediate_Dir "Release"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GR /GX /O2 /I "..\..\Sockets" /I "c:\openssl\include" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "HAVE_OPENSSL" /YX /FD /c
+# ADD BASE RSC /l 0x41d /d "NDEBUG"
+# ADD RSC /l 0x41d /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib Sockets.lib ssleay32md.lib libeay32md.lib /nologo /subsystem:console /machine:I386 /libpath:"\openssl\lib\vc" /libpath:"..\..\lib\r"
+
+!ELSEIF "$(CFG)" == "stressclient - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "D"
+# PROP Intermediate_Dir "Debug"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /MTd /W3 /Gm /GR /GX /ZI /Od /I "..\..\Sockets" /I "c:\openssl\include" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "HAVE_OPENSSL" /YX /FD /GZ /c
+# ADD BASE RSC /l 0x41d /d "_DEBUG"
+# ADD RSC /l 0x41d /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib Sockets.lib ssleay32md.lib libeay32md.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"\openssl\lib\vc" /libpath:"..\..\lib\d"
+
+!ENDIF
+
+# Begin Target
+
+# Name "stressclient - Win32 Release"
+# Name "stressclient - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\tests\stressclient.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/Sockets/README.macosx b/Sockets/README.macosx
new file mode 100644
index 0000000..b886673
--- /dev/null
+++ b/Sockets/README.macosx
@@ -0,0 +1,3 @@
+Find uuid.h here
+ http://www.die.net/doc/linux/include/uuid/uuid.h
+
diff --git a/Sockets/RandomNumber.cpp b/Sockets/RandomNumber.cpp
new file mode 100644
index 0000000..77ba30d
--- /dev/null
+++ b/Sockets/RandomNumber.cpp
@@ -0,0 +1,116 @@
+/**
+ * @author Adam McLaurin
+ * @date September 2006
+ */
+/*
+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
+GN6U 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.
+*/
+#include "RandomNumber.h"
+#include <limits>
+#include <time.h>
+
+#ifdef SOCKETS_NAMESPACE
+namespace SOCKETS_NAMESPACE {
+#endif
+
+const unsigned long int RandomNumber::X_SEED_DEFAULT = 123456789UL;
+const unsigned long int RandomNumber::Y_SEED_DEFAULT = 362436069UL;
+const unsigned long int RandomNumber::Z_SEED_DEFAULT = 521288629UL;
+const unsigned long int RandomNumber::W_SEED_DEFAULT = 88675123UL;
+
+
+RandomNumber::RandomNumber(bool time_shuffle)
+:mXSeed(time_shuffle ? (unsigned long)time(NULL) ^ X_SEED_DEFAULT : X_SEED_DEFAULT)
+,mYSeed(time_shuffle ? (unsigned long)time(NULL) ^ Y_SEED_DEFAULT : Y_SEED_DEFAULT)
+,mZSeed(time_shuffle ? (unsigned long)time(NULL) ^ Z_SEED_DEFAULT : Z_SEED_DEFAULT)
+,mWSeed(time_shuffle ? (unsigned long)time(NULL) ^ W_SEED_DEFAULT : W_SEED_DEFAULT)
+{
+ reset();
+}
+
+RandomNumber::RandomNumber(
+ unsigned long int x_seed,
+ unsigned long int y_seed,
+ unsigned long int z_seed,
+ unsigned long int w_seed)
+:mXSeed(x_seed)
+,mYSeed(y_seed)
+,mZSeed(z_seed)
+,mWSeed(w_seed)
+{
+ reset();
+}
+
+RandomNumber::~RandomNumber()
+{
+}
+
+void RandomNumber::reset()
+{
+ mX = mXSeed;
+ mY = mYSeed;
+ mZ = mZSeed;
+ mW = mWSeed;
+}
+
+RandomNumber::operator unsigned long int() const
+{
+ return(mW);
+}
+
+unsigned long int RandomNumber::next()
+{
+ register unsigned long int t = (mX ^ (mX<<11));
+
+ mX = mY;
+
+ mY = mZ;
+
+ mZ = mW;
+
+ return(mW = (mW ^ (mW>>19)) ^ (t ^ (t>>8)));
+}
+
+unsigned long int RandomNumber::skip(unsigned long int s)
+{
+ for(register unsigned long int i = 0 ; i < s ; ++i)
+ {
+ (void)next();
+ }
+
+ return(mW);
+}
+
+void RandomNumber::getSeed(
+ unsigned long int& x_seed,
+ unsigned long int& y_seed,
+ unsigned long int& z_seed,
+ unsigned long int& w_seed)
+{
+ x_seed = mXSeed;
+ y_seed = mYSeed;
+ z_seed = mZSeed;
+ w_seed = mWSeed;
+}
+
+unsigned long int RandomNumber::max_random()
+{
+ return(std::numeric_limits<unsigned long int>::max());
+}
+
+#ifdef SOCKETS_NAMESPACE
+} // namespace SOCKETS_NAMESPACE {
+#endif
+
diff --git a/Sockets/RandomNumber.h b/Sockets/RandomNumber.h
new file mode 100644
index 0000000..376db43
--- /dev/null
+++ b/Sockets/RandomNumber.h
@@ -0,0 +1,202 @@
+/**
+ * @author Adam McLaurin
+ * @date September 2006
+ */
+/*
+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.
+*/
+
+#ifndef _SOCKET_RandomNumber_H
+#define _SOCKET_RandomNumber_H
+
+#include "sockets-config.h"
+#include <limits>
+
+#ifdef SOCKETS_NAMESPACE
+namespace SOCKETS_NAMESPACE {
+#endif
+
+/**
+ * The following class uses an xorshift algorithm proposed in the following
+ * paper:
+ * - http://www.jstatsoft.org/v08/i14/xorshift.pdf
+ *
+ * The algorithm provides a PRNG with a period of (2^128)-1
+ *
+ * This PRNG is *not* intended for cryptographic purposes
+ */
+class RandomNumber
+{
+
+public:
+ /**
+ * Default constructor
+ *
+ * NOTE: Internal seeds are set to defaults proposed by the paper
+ */
+ RandomNumber(bool time_shuffle = false);
+
+ /**
+ * Custom constructor
+ *
+ * @param x_seed X seed
+ *
+ * @param y_seed Y seed
+ *
+ * @param z_seed Z seed
+ *
+ * @param w_seed W seed
+ */
+ RandomNumber(
+ unsigned long int x_seed,
+ unsigned long int y_seed,
+ unsigned long int z_seed,
+ unsigned long int w_seed);
+
+ /**
+ * Destructor
+ */
+ ~RandomNumber();
+
+ // public methods
+
+ /**
+ * Reset internal state to initial seed values
+ */
+ void reset();
+
+ /**
+ * Cast operator to obtain current random value in the PRNG
+ *
+ * @return Current random value in the PRNG
+ */
+ operator unsigned long int() const;
+
+ /**
+ * Go to the next number in the PRNG sequence
+ *
+ * NOTE: This method is a slightly modified implementation of the xor128()
+ * function proposed in the paper
+ *
+ * @return Next value produced by the PRNG (after updating)
+ */
+ unsigned long int next();
+
+ /**
+ * Skip ahead in the PRNG sequence by a given number of iterations
+ *
+ * @param s Number of iterations to skip ahead
+ *
+ * @return Value produced by the PRNG after skipping ahead in the sequence
+ */
+ unsigned long int skip(unsigned long int s);
+
+ /**
+ * Obtain all the initial seeds for this PRNG
+ *
+ * @param x_seed X seed (output)
+ *
+ * @param y_seed Y seed (output)
+ *
+ * @param z_seed Z seed (output)
+ *
+ * @param w_seed W seed (output)
+ */
+ void getSeed(
+ unsigned long int& x_seed,
+ unsigned long int& y_seed,
+ unsigned long int& z_seed,
+ unsigned long int& w_seed);
+
+ /**
+ * Get the maximum possible random number from this PRNG
+ *
+ * @return Maximum possible random number from this PRNG
+ */
+ static unsigned long int max_random();
+
+ // public constants
+
+ /**
+ * Default x-seed as proposed by the paper
+ */
+ static const unsigned long int X_SEED_DEFAULT;
+
+ /**
+ * Default y-seed as proposed by the paper
+ */
+ static const unsigned long int Y_SEED_DEFAULT;
+
+ /**
+ * Default z-seed as proposed by the paper
+ */
+ static const unsigned long int Z_SEED_DEFAULT;
+
+ /**
+ * Default w-seed as proposed by the paper
+ */
+ static const unsigned long int W_SEED_DEFAULT;
+
+private:
+ /**
+ * X seed
+ */
+ unsigned long int mXSeed;
+
+ /**
+ * Y seed
+ */
+ unsigned long int mYSeed;
+
+ /**
+ * Z seed
+ */
+ unsigned long int mZSeed;
+
+ /**
+ * W seed
+ */
+ unsigned long int mWSeed;
+
+ /**
+ * X value
+ */
+ unsigned long int mX;
+
+ /**
+ * Y value
+ */
+ unsigned long int mY;
+
+ /**
+ * Z value
+ */
+ unsigned long int mZ;
+
+ /**
+ * W value
+ *
+ * NOTE: This is the externally-visible next value produced by the PRNG
+ */
+ unsigned long int mW;
+
+};
+
+#ifdef SOCKETS_NAMESPACE
+} // namespace SOCKETS_NAMESPACE {
+#endif
+
+#endif // _SOCKETS_RandomNumber_H
+
diff --git a/Sockets/ResolvServer.cpp b/Sockets/ResolvServer.cpp
new file mode 100644
index 0000000..83f842b
--- /dev/null
+++ b/Sockets/ResolvServer.cpp
@@ -0,0 +1,97 @@
+/** \file ResolvServer.cpp
+ ** \date 2005-03-24
+ ** \author grymse@alhem.net
+**/
+/*
+Copyright (C) 2004-2007 Anders Hedstrom
+
+This library is made available under the terms of the GNU GPL.
+
+If you would like to use this library in a closed-source application,
+a separate license agreement is available. For information about
+the closed-source license agreement for the C++ sockets library,
+please visit http://www.alhem.net/Sockets/license.html and/or
+email license@alhem.net.
+
+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 _MSC_VER
+#pragma warning(disable:4786)
+#endif
+#include "ResolvServer.h"
+#ifdef ENABLE_RESOLVER
+#include "StdoutLog.h"
+#include "ListenSocket.h"
+#include "ResolvSocket.h"
+#include "SocketHandler.h"
+
+#ifdef SOCKETS_NAMESPACE
+namespace SOCKETS_NAMESPACE {
+#endif
+
+
+ResolvServer::ResolvServer(port_t port)
+:Thread()
+,m_quit(false)
+,m_port(port)
+,m_ready(false)
+{
+}
+
+
+ResolvServer::~ResolvServer()
+{
+}
+
+
+void ResolvServer::Run()
+{
+// StdoutLog log;
+ SocketHandler h;
+ ListenSocket<ResolvSocket> l(h);
+
+ if (l.Bind("127.0.0.1", m_port))
+ {
+ return;
+ }
+ h.Add(&l);
+
+ m_ready = true;
+ while (!m_quit && IsRunning() )
+ {
+ h.Select(0, 500000);
+ }
+ SetRunning(false);
+}
+
+
+void ResolvServer::Quit()
+{
+ m_quit = true;
+}
+
+
+bool ResolvServer::Ready()
+{
+ return m_ready;
+}
+
+
+#ifdef SOCKETS_NAMESPACE
+}
+#endif
+
+#endif // ENABLE_RESOLVER
+
diff --git a/Sockets/ResolvServer.h b/Sockets/ResolvServer.h
new file mode 100644
index 0000000..f8f8f5a
--- /dev/null
+++ b/Sockets/ResolvServer.h
@@ -0,0 +1,73 @@
+/** \file ResolvServer.h
+ ** \date 2005-03-24
+ ** \author grymse@alhem.net
+**/
+/*
+Copyright (C) 2004-2007 Anders Hedstrom
+
+This library is made available under the terms of the GNU GPL.
+
+If you would like to use this library in a closed-source application,
+a separate license agreement is available. For information about
+the closed-source license agreement for the C++ sockets library,
+please visit http://www.alhem.net/Sockets/license.html and/or
+email license@alhem.net.
+
+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.
+*/
+#ifndef _SOCKETS_ResolvServer_H
+#define _SOCKETS_ResolvServer_H
+#include "sockets-config.h"
+#ifdef ENABLE_RESOLVER
+#include "socket_include.h"
+#include "Thread.h"
+
+#ifdef SOCKETS_NAMESPACE
+namespace SOCKETS_NAMESPACE {
+#endif
+
+/** \defgroup async Asynchronous DNS */
+/** Async DNS resolver thread.
+ \ingroup async */
+class ResolvServer : public Thread
+{
+public:
+ ResolvServer(port_t);
+ ~ResolvServer();
+
+ void Run();
+ void Quit();
+
+ bool Ready();
+
+private:
+ ResolvServer(const ResolvServer& ) {} // copy constructor
+ ResolvServer& operator=(const ResolvServer& ) { return *this; } // assignment operator
+
+ bool m_quit;
+ port_t m_port;
+ bool m_ready;
+};
+
+
+
+
+#ifdef SOCKETS_NAMESPACE
+}
+#endif
+
+#endif // ENABLE_RESOLVER
+#endif // _SOCKETS_ResolvServer_H
+
diff --git a/Sockets/ResolvSocket.cpp b/Sockets/ResolvSocket.cpp
new file mode 100644
index 0000000..4a3644f
--- /dev/null
+++ b/Sockets/ResolvSocket.cpp
@@ -0,0 +1,436 @@
+/** \file ResolvSocket.cpp
+ ** \date 2005-03-24
+ ** \author grymse@alhem.net
+**/
+/*
+Copyright (C) 2004-2007 Anders Hedstrom
+
+This library is made available under the terms of the GNU GPL.
+
+If you would like to use this library in a closed-source application,
+a separate license agreement is available. For information about
+the closed-source license agreement for the C++ sockets library,
+please visit http://www.alhem.net/Sockets/license.html and/or
+email license@alhem.net.
+
+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
+#ifdef _MSC_VER
+#pragma warning(disable:4786)
+#pragma warning(disable:4503)
+#endif
+#else
+#include <netdb.h>
+#endif
+#include "ResolvSocket.h"
+#ifdef ENABLE_RESOLVER
+#include "Utility.h"
+#include "Parse.h"
+#include "ISocketHandler.h"
+#include "Lock.h"
+#include "Mutex.h"
+
+#ifdef SOCKETS_NAMESPACE
+namespace SOCKETS_NAMESPACE {
+#endif
+
+#ifdef _DEBUG
+#define DEB(x) x
+#else
+#define DEB(x)
+#endif
+
+
+// static
+ResolvSocket::cache_t ResolvSocket::m_cache;
+ResolvSocket::timeout_t ResolvSocket::m_cache_to;
+Mutex ResolvSocket::m_cache_mutex;
+
+
+ResolvSocket::ResolvSocket(ISocketHandler& h)
+:TcpSocket(h)
+,m_bServer(false)
+,m_parent(NULL)
+#ifdef ENABLE_IPV6
+,m_resolve_ipv6(false)
+#endif
+,m_cached(false)
+{
+ SetLineProtocol();
+}
+
+
+ResolvSocket::ResolvSocket(ISocketHandler& h, Socket *parent, const std::string& host, port_t port, bool ipv6)
+:TcpSocket(h)
+,m_bServer(false)
+,m_parent(parent)
+,m_resolv_host(host)
+,m_resolv_port(port)
+#ifdef ENABLE_IPV6
+,m_resolve_ipv6(ipv6)
+#endif
+,m_cached(false)
+{
+ SetLineProtocol();
+}
+
+
+ResolvSocket::ResolvSocket(ISocketHandler& h, Socket *parent, ipaddr_t a)
+:TcpSocket(h)
+,m_bServer(false)
+,m_parent(parent)
+,m_resolv_port(0)
+,m_resolv_address(a)
+#ifdef ENABLE_IPV6
+,m_resolve_ipv6(false)
+#endif
+,m_cached(false)
+{
+ SetLineProtocol();
+}
+
+
+#ifdef ENABLE_IPV6
+ResolvSocket::ResolvSocket(ISocketHandler& h, Socket *parent, in6_addr& a)
+:TcpSocket(h)
+,m_bServer(false)
+,m_parent(parent)
+,m_resolv_port(0)
+,m_resolve_ipv6(true)
+,m_resolv_address6(a)
+,m_cached(false)
+{
+ SetLineProtocol();
+}
+#endif
+
+
+ResolvSocket::~ResolvSocket()
+{
+}
+
+
+void ResolvSocket::OnLine(const std::string& line)
+{
+ Parse pa(line, ":");
+ if (m_bServer)
+ {
+ m_query = pa.getword();
+ m_data = pa.getrest();
+DEB( fprintf(stderr, " *** ResolvSocket server; query=%s, data=%s\n", m_query.c_str(), m_data.c_str());)
+ // %! check cache
+ {
+ Lock lock(m_cache_mutex);
+ if (m_cache[m_query].find(m_data) != m_cache[m_query].end())
+ {
+ if (time(NULL) - m_cache_to[m_query][m_data] < 3600) // ttl
+ {
+ std::string result = m_cache[m_query][m_data];
+DEB(fprintf(stderr, " *** Returning cache for [%s][%s] = '%s'\n", m_query.c_str(), m_data.c_str(), result.c_str());)
+ Send("Cached\n");
+ if (!result.size()) /* failed */
+ {
+ Send("Failed\n\n");
+ SetCloseAndDelete();
+ return;
+ }
+ else
+ if (m_query == "gethostbyname")
+ {
+ Send("A: " + result + "\n\n");
+ SetCloseAndDelete();
+ return;
+ }
+ else
+#ifdef ENABLE_IPV6
+#ifdef IPPROTO_IPV6
+ if (m_query == "gethostbyname2")
+ {
+ Send("AAAA: " + result + "\n\n");
+ SetCloseAndDelete();
+ return;
+ }
+ else
+#endif
+#endif
+ if (m_query == "gethostbyaddr")
+ {
+ Send("Name: " + result + "\n\n");
+ SetCloseAndDelete();
+ return;
+ }
+ }
+ }
+ }
+ if (!Detach()) // detach failed?
+ {
+ SetCloseAndDelete();
+ }
+ return;
+ }
+ std::string key = pa.getword();
+ std::string value = pa.getrest();
+DEB( fprintf(stderr, " *** ResolvSocket response; %s: %s\n", key.c_str(), value.c_str());)
+
+ if (key == "Cached")
+ {
+ m_cached = true;
+ }
+ else
+ if (key == "Failed" && m_parent)
+ {
+DEB( fprintf(stderr, " ************ Resolve failed\n");)
+ if (Handler().Resolving(m_parent) || Handler().Valid(m_parent))
+ {
+ m_parent -> OnResolveFailed(m_resolv_id);
+ }
+ // update cache
+ if (!m_cached)
+ {
+ Lock lock(m_cache_mutex);
+DEB(fprintf(stderr, " *** Update cache for [%s][%s] = '%s'\n", m_query.c_str(), m_data.c_str(), value.c_str());)
+ m_cache[m_query][m_data] = value;
+ m_cache_to[m_query][m_data] = time(NULL);
+ }
+ m_parent = NULL;
+ }
+ else
+ if (key == "Name" && !m_resolv_host.size() && m_parent)
+ {
+ if (Handler().Resolving(m_parent) || Handler().Valid(m_parent))
+ {
+ m_parent -> OnReverseResolved(m_resolv_id, value);
+ }
+ // update cache
+ if (!m_cached)
+ {
+ Lock lock(m_cache_mutex);
+DEB(fprintf(stderr, " *** Update cache for [%s][%s] = '%s'\n", m_query.c_str(), m_data.c_str(), value.c_str());)
+ m_cache[m_query][m_data] = value;
+ m_cache_to[m_query][m_data] = time(NULL);
+ }
+ m_parent = NULL;
+ }
+ else
+ if (key == "A" && m_parent)
+ {
+ if (Handler().Resolving(m_parent) || Handler().Valid(m_parent))
+ {
+ ipaddr_t l;
+ Utility::u2ip(value, l); // ip2ipaddr_t
+ m_parent -> OnResolved(m_resolv_id, l, m_resolv_port);
+ }
+ // update cache
+ if (!m_cached)
+ {
+ Lock lock(m_cache_mutex);
+DEB(fprintf(stderr, " *** Update cache for [%s][%s] = '%s'\n", m_query.c_str(), m_data.c_str(), value.c_str());)
+ m_cache[m_query][m_data] = value;
+ m_cache_to[m_query][m_data] = time(NULL);
+ }
+ m_parent = NULL; // always use first ip in case there are several
+ }
+#ifdef ENABLE_IPV6
+#ifdef IPPROTO_IPV6
+ else
+ if (key == "AAAA" && m_parent)
+ {
+ if (Handler().Resolving(m_parent) || Handler().Valid(m_parent))
+ {
+ in6_addr a;
+ Utility::u2ip(value, a);
+ m_parent -> OnResolved(m_resolv_id, a, m_resolv_port);
+ }
+ // update cache
+ if (!m_cached)
+ {
+ Lock lock(m_cache_mutex);
+DEB(fprintf(stderr, " *** Update cache for [%s][%s] = '%s'\n", m_query.c_str(), m_data.c_str(), value.c_str());)
+ m_cache[m_query][m_data] = value;
+ m_cache_to[m_query][m_data] = time(NULL);
+ }
+ m_parent = NULL;
+ }
+#endif
+#endif
+}
+
+
+void ResolvSocket::OnDetached()
+{
+DEB( fprintf(stderr, " *** ResolvSocket::OnDetached(); query=%s, data=%s\n", m_query.c_str(), m_data.c_str());)
+ if (m_query == "gethostbyname")
+ {
+ struct sockaddr_in sa;
+ if (Utility::u2ip(m_data, sa))
+ {
+ std::string ip;
+ Utility::l2ip(sa.sin_addr, ip);
+ Send("A: " + ip + "\n");
+ }
+ else
+ {
+ Send("Failed\n");
+ }
+ Send("\n");
+ }
+ else
+#ifdef ENABLE_IPV6
+#ifdef IPPROTO_IPV6
+ if (m_query == "gethostbyname2")
+ {
+ struct sockaddr_in6 sa;
+ if (Utility::u2ip(m_data, sa))
+ {
+ std::string ip;
+ Utility::l2ip(sa.sin6_addr, ip);
+ Send("AAAA: " + ip + "\n");
+ }
+ else
+ {
+ Send("Failed\n");
+ }
+ Send("\n");
+ }
+ else
+#endif
+#endif
+ if (m_query == "gethostbyaddr")
+ {
+ if (Utility::isipv4( m_data ))
+ {
+ struct sockaddr_in sa;
+ if (!Utility::u2ip(m_data, sa, AI_NUMERICHOST))
+ {
+ Send("Failed: convert to sockaddr_in failed\n");
+ }
+ else
+ {
+ std::string name;
+ if (!Utility::reverse( (struct sockaddr *)&sa, sizeof(sa), name))
+ {
+ Send("Failed: ipv4 reverse lookup of " + m_data + "\n");
+ }
+ else
+ {
+ Send("Name: " + name + "\n");
+ }
+ }
+ }
+ else
+#ifdef ENABLE_IPV6
+#ifdef IPPROTO_IPV6
+ if (Utility::isipv6( m_data ))
+ {
+ struct sockaddr_in6 sa;
+ if (!Utility::u2ip(m_data, sa, AI_NUMERICHOST))
+ {
+ Send("Failed: convert to sockaddr_in6 failed\n");
+ }
+ else
+ {
+ std::string name;
+ if (!Utility::reverse( (struct sockaddr *)&sa, sizeof(sa), name))
+ {
+ Send("Failed: ipv6 reverse lookup of " + m_data + "\n");
+ }
+ else
+ {
+ Send("Name: " + name + "\n");
+ }
+ }
+ }
+ else
+#endif
+#endif
+ {
+ Send("Failed: malformed address\n");
+ }
+ Send("\n");
+ }
+ else
+ {
+ std::string msg = "Unknown query type: " + m_query;
+ Handler().LogError(this, "OnDetached", 0, msg);
+ Send("Unknown\n\n");
+ }
+ SetCloseAndDelete();
+}
+
+
+void ResolvSocket::OnConnect()
+{
+ if (m_resolv_host.size())
+ {
+#ifdef ENABLE_IPV6
+ std::string msg = (m_resolve_ipv6 ? "gethostbyname2 " : "gethostbyname ") + m_resolv_host + "\n";
+ m_query = m_resolve_ipv6 ? "gethostbyname2" : "gethostbyname";
+#else
+ std::string msg = "gethostbyname " + m_resolv_host + "\n";
+ m_query = "gethostbyname";
+#endif
+ m_data = m_resolv_host;
+ Send( msg );
+ return;
+ }
+#ifdef ENABLE_IPV6
+ if (m_resolve_ipv6)
+ {
+ std::string tmp;
+ Utility::l2ip(m_resolv_address6, tmp);
+ m_query = "gethostbyaddr";
+ m_data = tmp;
+ std::string msg = "gethostbyaddr " + tmp + "\n";
+ Send( msg );
+ }
+#endif
+ std::string tmp;
+ Utility::l2ip(m_resolv_address, tmp);
+ m_query = "gethostbyaddr";
+ m_data = tmp;
+ std::string msg = "gethostbyaddr " + tmp + "\n";
+ Send( msg );
+}
+
+
+void ResolvSocket::OnDelete()
+{
+ if (m_parent)
+ {
+ if (Handler().Resolving(m_parent) || Handler().Valid(m_parent))
+ {
+ m_parent -> OnResolveFailed(m_resolv_id);
+ }
+ // update cache
+ if (!m_cached)
+ {
+ Lock lock(m_cache_mutex);
+ std::string value;
+DEB(fprintf(stderr, " *** Update cache for [%s][%s] = '%s'\n", m_query.c_str(), m_data.c_str(), value.c_str());)
+ m_cache[m_query][m_data] = value;
+ m_cache_to[m_query][m_data] = time(NULL);
+ }
+ m_parent = NULL;
+ }
+}
+
+
+#ifdef SOCKETS_NAMESPACE
+}
+#endif
+
+#endif // ENABLE_RESOLVER
+
diff --git a/Sockets/ResolvSocket.h b/Sockets/ResolvSocket.h
new file mode 100644
index 0000000..ff4b1a5
--- /dev/null
+++ b/Sockets/ResolvSocket.h
@@ -0,0 +1,106 @@
+/** \file ResolvSocket.h
+ ** \date 2005-03-24
+ ** \author grymse@alhem.net
+**/
+/*
+Copyright (C) 2004-2007 Anders Hedstrom
+
+This library is made available under the terms of the GNU GPL.
+
+If you would like to use this library in a closed-source application,
+a separate license agreement is available. For information about
+the closed-source license agreement for the C++ sockets library,
+please visit http://www.alhem.net/Sockets/license.html and/or
+email license@alhem.net.
+
+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.
+*/
+#ifndef _SOCKETS_ResolvSocket_H
+#define _SOCKETS_ResolvSocket_H
+#include "sockets-config.h"
+#ifdef ENABLE_RESOLVER
+#include "TcpSocket.h"
+#include <map>
+
+#ifdef SOCKETS_NAMESPACE
+namespace SOCKETS_NAMESPACE {
+#endif
+
+class Mutex;
+
+/** Async DNS resolver socket.
+ \ingroup async */
+class ResolvSocket : public TcpSocket
+{
+ typedef std::map<std::string, /* type */
+ std::map<std::string, std::string> > cache_t; /* host, result */
+ typedef std::map<std::string, /* type */
+ std::map<std::string, time_t> > timeout_t; /* host, time */
+
+public:
+ ResolvSocket(ISocketHandler&);
+ ResolvSocket(ISocketHandler&, Socket *parent, const std::string& host, port_t port, bool ipv6 = false);
+ ResolvSocket(ISocketHandler&, Socket *parent, ipaddr_t);
+#ifdef ENABLE_IPV6
+ ResolvSocket(ISocketHandler&, Socket *parent, in6_addr&);
+#endif
+ ~ResolvSocket();
+
+ void OnAccept() { m_bServer = true; }
+ void OnLine(const std::string& line);
+ void OnDetached();
+ void OnDelete();
+
+ void SetId(int x) { m_resolv_id = x; }
+ int GetId() { return m_resolv_id; }
+
+ void OnConnect();
+
+#ifdef ENABLE_IPV6
+ void SetResolveIpv6(bool x = true) { m_resolve_ipv6 = x; }
+#endif
+
+private:
+ ResolvSocket(const ResolvSocket& s) : TcpSocket(s) {} // copy constructor
+ ResolvSocket& operator=(const ResolvSocket& ) { return *this; } // assignment operator
+
+ std::string m_query;
+ std::string m_data;
+ bool m_bServer;
+ Socket *m_parent;
+ int m_resolv_id;
+ std::string m_resolv_host;
+ port_t m_resolv_port;
+ ipaddr_t m_resolv_address;
+#ifdef ENABLE_IPV6
+ bool m_resolve_ipv6;
+ in6_addr m_resolv_address6;
+#endif
+ static cache_t m_cache;
+ static timeout_t m_cache_to;
+ static Mutex m_cache_mutex;
+ bool m_cached;
+};
+
+
+
+
+#ifdef SOCKETS_NAMESPACE
+}
+#endif
+
+#endif // ENABLE_RESOLVER
+#endif // _SOCKETS_ResolvSocket_H
+
diff --git a/Sockets/SSLInitializer.cpp b/Sockets/SSLInitializer.cpp
new file mode 100644
index 0000000..65218b1
--- /dev/null
+++ b/Sockets/SSLInitializer.cpp
@@ -0,0 +1,144 @@
+/**
+ ** \file SSLInitializer.cpp
+ ** \date 2007-04-30
+ ** \author grymse@alhem.net
+**/
+/*
+Copyright (C) 2007 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
+#ifdef _MSC_VER
+#pragma warning(disable:4786)
+#endif
+#include <io.h>
+#endif
+#include "SSLInitializer.h"
+#ifdef HAVE_OPENSSL
+#include <map>
+#include "Utility.h"
+#include <openssl/rand.h>
+#include "Mutex.h"
+
+#ifdef _DEBUG
+#define DEB(x) x
+#else
+#define DEB(x)
+#endif
+
+
+#ifdef SOCKETS_NAMESPACE
+namespace SOCKETS_NAMESPACE {
+#endif
+
+
+
+SSLInitializer::SSLInitializer()
+{
+DEB( fprintf(stderr, "SSLInitializer()\n");)
+
+ bio_err = NULL;
+ m_rand_size = 1024;
+
+ /* An error write context */
+ bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
+
+ /* Global system initialization*/
+ SSL_library_init();
+ SSL_load_error_strings();
+ OpenSSL_add_all_algorithms();
+ CRYPTO_set_locking_callback( SSL_locking_function );
+ CRYPTO_set_id_callback( SSL_id_function );
+
+ char *randfile = getenv("RANDFILE");
+ char *home = getenv("HOME");
+ if (!randfile && !home)
+ {
+ char *homepath = getenv("HOMEPATH");
+ if (homepath)
+ {
+ Utility::SetEnv("HOME", homepath);
+ }
+ }
+ char path[512];
+ *path = 0;
+ RAND_file_name(path, 512);
+ if (*path)
+ {
+ m_rand_file = path;
+ m_rand_size = 1024;
+ RAND_write_file(path);
+ }
+ else
+ {
+DEB( fprintf(stderr, "SSLInitializer: no random file generated\n");)
+ }
+
+ /* Load randomness */
+ if (!m_rand_file.size() || !RAND_load_file(m_rand_file.c_str(), m_rand_size))
+ {
+DEB( fprintf(stderr, "SSLInitializer: PRNG not initialized\n");)
+ }
+
+}
+
+
+SSLInitializer::~SSLInitializer()
+{
+DEB( fprintf(stderr, "~SSLInitializer()\n");)
+ DeleteRandFile();
+ // %! delete mutexes
+}
+
+
+void SSLInitializer::DeleteRandFile()
+{
+ if (m_rand_file.size())
+ {
+ unlink(m_rand_file.c_str());
+ }
+}
+
+
+void SSLInitializer::SSL_locking_function(int mode, int n, const char *file, int line)
+{
+static std::map<int, Mutex *> mmap;
+ if (mmap.find(n) == mmap.end())
+ {
+ mmap[n] = new Mutex;
+ }
+ if (mode & CRYPTO_LOCK)
+ {
+ mmap[n] -> Lock();
+ }
+ else
+ {
+ mmap[n] -> Unlock();
+ }
+}
+
+
+unsigned long SSLInitializer::SSL_id_function()
+{
+ return Utility::ThreadID();
+}
+
+
+#ifdef SOCKETS_NAMESPACE
+} // namespace SOCKETS_NAMESPACE {
+#endif
+#endif // HAVE_OPENSSL
+
diff --git a/Sockets/SSLInitializer.h b/Sockets/SSLInitializer.h
new file mode 100644
index 0000000..9f81d1c
--- /dev/null
+++ b/Sockets/SSLInitializer.h
@@ -0,0 +1,76 @@
+/**
+ ** \file SSLInitializer.h
+ ** \date 2007-04-30
+ ** \author grymse@alhem.net
+**/
+/*
+Copyright (C) 2007 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.
+*/
+#ifndef __SOCKETS_SSLInitializer_H
+#define __SOCKETS_SSLInitializer_H
+#include "sockets-config.h"
+#ifdef HAVE_OPENSSL
+
+#include <openssl/ssl.h>
+#include <string>
+
+
+#ifdef SOCKETS_NAMESPACE
+namespace SOCKETS_NAMESPACE {
+#endif
+
+
+class SSLInitializer
+{
+public:
+ /**
+ init openssl
+ bio_err
+ create random file
+ */
+ SSLInitializer();
+
+ /**
+ remove random file
+ */
+ ~SSLInitializer();
+
+ void DeleteRandFile();
+
+ /** SSL; mutex locking function callback. */
+static void SSL_locking_function(int mode, int n, const char *file, int line);
+
+ /** Return thread id. */
+static unsigned long SSL_id_function();
+
+ BIO *bio_err;
+
+private:
+ std::string m_rand_file;
+ long m_rand_size;
+
+};
+
+
+
+
+#ifdef SOCKETS_NAMESPACE
+} // namespace SOCKETS_NAMESPACE {
+#endif
+#endif // HAVE_OPENSSL
+#endif // __SOCKETS_SSLInitializer_H
+
diff --git a/Sockets/SctpSocket.cpp b/Sockets/SctpSocket.cpp
new file mode 100644
index 0000000..2267086
--- /dev/null
+++ b/Sockets/SctpSocket.cpp
@@ -0,0 +1,496 @@
+/**
+ ** \file SctpSocket.cpp
+ ** \date 2006-09-04
+ ** \author grymse@alhem.net
+**/
+/*
+Copyright (C) 2007 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.
+*/
+#include "SctpSocket.h"
+#ifdef USE_SCTP
+#include "Utility.h"
+#include "ISocketHandler.h"
+#include <errno.h>
+#include "Ipv4Address.h"
+#include "Ipv6Address.h"
+#ifdef ENABLE_EXCEPTIONS
+#include "Exception.h"
+#endif
+
+#ifdef SOCKETS_NAMESPACE
+namespace SOCKETS_NAMESPACE
+{
+#endif
+
+
+SctpSocket::SctpSocket(ISocketHandler& h,int type) : StreamSocket(h)
+,m_type(type)
+,m_buf(new char[SCTP_BUFSIZE_READ])
+{
+ if (type != SOCK_STREAM && type != SOCK_SEQPACKET)
+ {
+ }
+}
+
+
+SctpSocket::~SctpSocket()
+{
+ delete[] m_buf;
+}
+
+
+int SctpSocket::Bind(const std::string& a,port_t p)
+{
+#ifdef ENABLE_IPV6
+#ifdef IPPROTO_IPV6
+ if (IsIpv6())
+ {
+ Ipv6Address ad(a, p);
+ return Bind(ad);
+ }
+#endif
+#endif
+ Ipv4Address ad(a, p);
+ return Bind(ad);
+}
+
+
+int SctpSocket::Bind(SocketAddress& ad)
+{
+ if (!ad.IsValid())
+ {
+ Handler().LogError(this, "SctpSocket", -1, "invalid address", LOG_LEVEL_ERROR);
+ return -1;
+ }
+ if (GetSocket() == INVALID_SOCKET)
+ {
+ Attach(CreateSocket(ad.GetFamily(), m_type, "sctp"));
+ }
+ if (GetSocket() != INVALID_SOCKET)
+ {
+ int n = bind(GetSocket(), ad, ad);
+ if (n == -1)
+ {
+ Handler().LogError(this, "SctpSocket", -1, "bind() failed", LOG_LEVEL_ERROR);
+#ifdef ENABLE_EXCEPTIONS
+ throw Exception("bind() failed for SctpSocket, port: " + Utility::l2string(ad.GetPort()));
+#endif
+ }
+ return n;
+ }
+ return -1;
+}
+
+
+int SctpSocket::AddAddress(const std::string& a,port_t p)
+{
+#ifdef ENABLE_IPV6
+#ifdef IPPROTO_IPV6
+ if (IsIpv6())
+ {
+ Ipv6Address ad(a, p);
+ return AddAddress(ad);
+ }
+#endif
+#endif
+ Ipv4Address ad(a, p);
+ return AddAddress(ad);
+}
+
+
+int SctpSocket::AddAddress(SocketAddress& ad)
+{
+ if (!ad.IsValid())
+ {
+ Handler().LogError(this, "SctpSocket", -1, "invalid address", LOG_LEVEL_ERROR);
+ return -1;
+ }
+ if (GetSocket() == INVALID_SOCKET)
+ {
+ Handler().LogError(this, "SctpSocket", -1, "AddAddress called with invalid file descriptor", LOG_LEVEL_ERROR);
+ return -1;
+ }
+ int n = sctp_bindx(GetSocket(), ad, ad, SCTP_BINDX_ADD_ADDR);
+ if (n == -1)
+ {
+ Handler().LogError(this, "SctpSocket", -1, "sctp_bindx() failed", LOG_LEVEL_ERROR);
+ }
+ return n;
+}
+
+
+int SctpSocket::RemoveAddress(const std::string& a,port_t p)
+{
+#ifdef ENABLE_IPV6
+#ifdef IPPROTO_IPV6
+ if (IsIpv6())
+ {
+ Ipv6Address ad(a, p);
+ return RemoveAddress(ad);
+ }
+#endif
+#endif
+ Ipv4Address ad(a, p);
+ return RemoveAddress(ad);
+}
+
+
+int SctpSocket::RemoveAddress(SocketAddress& ad)
+{
+ if (!ad.IsValid())
+ {
+ Handler().LogError(this, "SctpSocket", -1, "invalid address", LOG_LEVEL_ERROR);
+ return -1;
+ }
+ if (GetSocket() == INVALID_SOCKET)
+ {
+ Handler().LogError(this, "SctpSocket", -1, "RemoveAddress called with invalid file descriptor", LOG_LEVEL_ERROR);
+ return -1;
+ }
+ int n = sctp_bindx(GetSocket(), ad, ad, SCTP_BINDX_REM_ADDR);
+ if (n == -1)
+ {
+ Handler().LogError(this, "SctpSocket", -1, "sctp_bindx() failed", LOG_LEVEL_ERROR);
+ }
+ return n;
+}
+
+
+int SctpSocket::Open(const std::string& a,port_t p)
+{
+#ifdef ENABLE_IPV6
+#ifdef IPPROTO_IPV6
+ if (IsIpv6())
+ {
+ Ipv6Address ad(a, p);
+ return Open(ad);
+ }
+#endif
+#endif
+ Ipv4Address ad(a, p);
+ return Open(ad);
+}
+
+
+int SctpSocket::Open(SocketAddress& ad)
+{
+ if (!ad.IsValid())
+ {
+ Handler().LogError(this, "SctpSocket", -1, "invalid address", LOG_LEVEL_ERROR);
+ return -1;
+ }
+ if (GetSocket() == INVALID_SOCKET)
+ {
+ Attach(CreateSocket(ad.GetFamily(), m_type, "sctp"));
+ }
+ if (GetSocket() != INVALID_SOCKET)
+ {
+ if (!SetNonblocking(true))
+ {
+ return -1;
+ }
+ int n = connect(GetSocket(), ad, ad);
+ if (n == -1)
+ {
+ // check error code that means a connect is in progress
+#ifdef _WIN32
+ if (Errno == WSAEWOULDBLOCK)
+#else
+ if (Errno == EINPROGRESS)
+#endif
+ {
+ Handler().LogError(this, "connect: connection pending", Errno, StrError(Errno), LOG_LEVEL_INFO);
+ SetConnecting( true ); // this flag will control fd_set's
+ }
+ else
+ {
+ Handler().LogError(this, "SctpSocket", -1, "connect() failed", LOG_LEVEL_ERROR);
+ }
+ }
+ return n;
+ }
+ return -1;
+}
+
+
+#ifndef SOLARIS
+int SctpSocket::AddConnection(const std::string& a,port_t p)
+{
+#ifdef ENABLE_IPV6
+#ifdef IPPROTO_IPV6
+ if (IsIpv6())
+ {
+ Ipv6Address ad(a, p);
+ return AddConnection(ad);
+ }
+#endif
+#endif
+ Ipv4Address ad(a, p);
+ return AddConnection(ad);
+}
+
+
+int SctpSocket::AddConnection(SocketAddress& ad)
+{
+ if (!ad.IsValid())
+ {
+ Handler().LogError(this, "SctpSocket", -1, "invalid address", LOG_LEVEL_ERROR);
+ return -1;
+ }
+ if (GetSocket() == INVALID_SOCKET)
+ {
+ Handler().LogError(this, "SctpSocket", -1, "AddConnection called with invalid file descriptor", LOG_LEVEL_ERROR);
+ return -1;
+ }
+ int n = sctp_connectx(GetSocket(), ad, ad);
+ if (n == -1)
+ {
+ Handler().LogError(this, "SctpSocket", -1, "sctp_connectx() failed", LOG_LEVEL_ERROR);
+ }
+ else
+ {
+ SetConnecting();
+ }
+ return n;
+}
+#endif
+
+
+int SctpSocket::getpaddrs(sctp_assoc_t id,std::list<std::string>& vec)
+{
+ struct sockaddr *p = NULL;
+ int n = sctp_getpaddrs(GetSocket(), id, &p);
+ if (!n || n == -1)
+ {
+ Handler().LogError(this, "SctpSocket", -1, "sctp_getpaddrs failed", LOG_LEVEL_WARNING);
+ return n;
+ }
+ for (int i = 0; i < n; i++)
+ {
+ vec.push_back(Utility::Sa2String(&p[i]));
+ }
+ sctp_freepaddrs(p);
+ return n;
+}
+
+
+int SctpSocket::getladdrs(sctp_assoc_t id,std::list<std::string>& vec)
+{
+ struct sockaddr *p = NULL;
+ int n = sctp_getladdrs(GetSocket(), id, &p);
+ if (!n || n == -1)
+ {
+ Handler().LogError(this, "SctpSocket", -1, "sctp_getladdrs failed", LOG_LEVEL_WARNING);
+ return n;
+ }
+ for (int i = 0; i < n; i++)
+ {
+ vec.push_back(Utility::Sa2String(&p[i]));
+ }
+ sctp_freeladdrs(p);
+ return n;
+}
+
+
+int SctpSocket::PeelOff(sctp_assoc_t id)
+{
+ int n = sctp_peeloff(GetSocket(), id);
+ if (n == -1)
+ {
+ Handler().LogError(this, "SctpSocket", -1, "PeelOff failed", LOG_LEVEL_WARNING);
+ return -1;
+ }
+ Socket *p = Create();
+ p -> Attach(n);
+ p -> SetDeleteByHandler();
+ Handler().Add(p);
+ return n;
+}
+
+
+void SctpSocket::OnRead()
+{
+/*
+ int sctp_recvmsg(int sd, void * msg, size_t * len,
+ struct sockaddr * from, socklen_t * fromlen,
+ struct sctp_sndrcvinfo * sinfo, int * msg_flags);
+
+ DESCRIPTION
+ sctp_recvmsg is a wrapper library function that can be used to receive a message from a socket while using the advanced
+ features of SCTP. sd is the socket descriptor on which the message pointed to by msg of length len is received.
+
+ If from is not NULL, the source address of the message is filled in. The argument fromlen is a value-result parameter.
+ initialized to the size of the buffer associated with from , and modified on return to indicate the actual size of the
+ address stored.
+
+ sinfo is a pointer to a sctp_sndrcvinfo structure to be filled upon receipt of the message. msg_flags is a pointer to a
+ integer that is filled with any message flags like MSG_NOTIFICATION or MSG_EOR.
+
+*/
+ struct sockaddr sa;
+ socklen_t sa_len = 0;
+ struct sctp_sndrcvinfo sinfo;
+ int flags = 0;
+ int n = sctp_recvmsg(GetSocket(), m_buf, SCTP_BUFSIZE_READ, &sa, &sa_len, &sinfo, &flags);
+ if (n == -1)
+ {
+ Handler().LogError(this, "SctpSocket", Errno, StrError(Errno), LOG_LEVEL_FATAL);
+ SetCloseAndDelete();
+ }
+ else
+ {
+ OnReceiveMessage(m_buf, n, &sa, sa_len, &sinfo, flags);
+ }
+}
+
+
+void SctpSocket::OnReceiveMessage(const char *buf,size_t sz,struct sockaddr *sa,socklen_t sa_len,struct sctp_sndrcvinfo *sinfo,int msg_flags)
+{
+}
+
+
+void SctpSocket::OnWrite()
+{
+ if (Connecting())
+ {
+ int err = SoError();
+
+ // don't reset connecting flag on error here, we want the OnConnectFailed timeout later on
+ /// \todo add to read fd_set here
+ if (!err) // ok
+ {
+ Set(!IsDisableRead(), false);
+ SetConnecting(false);
+ SetCallOnConnect();
+ return;
+ }
+ Handler().LogError(this, "sctp: connect failed", err, StrError(err), LOG_LEVEL_FATAL);
+ Set(false, false); // no more monitoring because connection failed
+
+ // failed
+#ifdef ENABLE_SOCKS4
+ if (Socks4())
+ {
+ OnSocks4ConnectFailed();
+ return;
+ }
+#endif
+ if (GetConnectionRetry() == -1 ||
+ (GetConnectionRetry() && GetConnectionRetries() < GetConnectionRetry()) )
+ {
+ // even though the connection failed at once, only retry after
+ // the connection timeout.
+ // should we even try to connect again, when CheckConnect returns
+ // false it's because of a connection error - not a timeout...
+ return;
+ }
+ SetConnecting(false);
+ SetCloseAndDelete( true );
+ /// \todo state reason why connect failed
+ OnConnectFailed();
+ return;
+ }
+}
+
+
+void SctpSocket::OnConnectTimeout()
+{
+ Handler().LogError(this, "connect", -1, "connect timeout", LOG_LEVEL_FATAL);
+#ifdef ENABLE_SOCKS4
+ if (Socks4())
+ {
+ OnSocks4ConnectFailed();
+ // retry direct connection
+ }
+ else
+#endif
+ if (GetConnectionRetry() == -1 ||
+ (GetConnectionRetry() && GetConnectionRetries() < GetConnectionRetry()) )
+ {
+ IncreaseConnectionRetries();
+ // ask socket via OnConnectRetry callback if we should continue trying
+ if (OnConnectRetry())
+ {
+ SetRetryClientConnect();
+ }
+ else
+ {
+ SetCloseAndDelete( true );
+ /// \todo state reason why connect failed
+ OnConnectFailed();
+ }
+ }
+ else
+ {
+ SetCloseAndDelete(true);
+ /// \todo state reason why connect failed
+ OnConnectFailed();
+ }
+ //
+ SetConnecting(false);
+}
+
+
+#ifdef _WIN32
+void SctpSocket::OnException()
+{
+ if (Connecting())
+ {
+#ifdef ENABLE_SOCKS4
+ if (Socks4())
+ OnSocks4ConnectFailed();
+ else
+#endif
+ if (GetConnectionRetry() == -1 ||
+ (GetConnectionRetry() &&
+ GetConnectionRetries() < GetConnectionRetry() ))
+ {
+ // even though the connection failed at once, only retry after
+ // the connection timeout
+ // should we even try to connect again, when CheckConnect returns
+ // false it's because of a connection error - not a timeout...
+ }
+ else
+ {
+ SetConnecting(false); // tnx snibbe
+ SetCloseAndDelete();
+ OnConnectFailed();
+ }
+ return;
+ }
+ // %! exception doesn't always mean something bad happened, this code should be reworked
+ // errno valid here?
+ int err = SoError();
+ Handler().LogError(this, "exception on select", err, StrError(err), LOG_LEVEL_FATAL);
+ SetCloseAndDelete();
+}
+#endif // _WIN32
+
+
+int SctpSocket::Protocol()
+{
+ return IPPROTO_SCTP;
+}
+
+
+#ifdef SOCKETS_NAMESPACE
+} // namespace SOCKETS_NAMESPACE
+#endif
+
+
+#endif // USE_SCTP
+
diff --git a/Sockets/SctpSocket.h b/Sockets/SctpSocket.h
new file mode 100644
index 0000000..12e72a0
--- /dev/null
+++ b/Sockets/SctpSocket.h
@@ -0,0 +1,110 @@
+/**
+ ** \file SctpSocket.h
+ ** \date 2006-09-04
+ ** \author grymse@alhem.net
+**/
+/*
+Copyright (C) 2007 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.
+*/
+#ifndef _SOCKETS_SctpSocket_H
+#define _SOCKETS_SctpSocket_H
+#include "sockets-config.h"
+
+#include <map>
+#include "StreamSocket.h"
+#ifdef USE_SCTP
+#include <netinet/sctp.h>
+
+#ifdef SOCKETS_NAMESPACE
+namespace SOCKETS_NAMESPACE {
+#endif
+
+#define SCTP_BUFSIZE_READ 16400
+
+class SocketAddress;
+
+
+class SctpSocket : public StreamSocket
+{
+public:
+ /** SctpSocket constructor.
+ \param h Owner
+ \param type SCTP_STREAM or SCTP_SEQPACKET */
+ SctpSocket(ISocketHandler& h,int type);
+ ~SctpSocket();
+
+ /** bind() */
+ int Bind(const std::string&,port_t);
+ int Bind(SocketAddress&);
+ /** sctp_bindx() */
+ int AddAddress(const std::string&,port_t);
+ int AddAddress(SocketAddress&);
+ /** sctp_bindx() */
+ int RemoveAddress(const std::string&,port_t);
+ int RemoveAddress(SocketAddress&);
+
+ /** connect() */
+ int Open(const std::string&,port_t);
+ int Open(SocketAddress&);
+
+ /** Connect timeout callback. */
+ void OnConnectTimeout();
+#ifdef _WIN32
+ /** Connection failed reported as exception on win32 */
+ void OnException();
+#endif
+
+#ifndef SOLARIS
+ /** sctp_connectx() */
+ int AddConnection(const std::string&,port_t);
+ int AddConnection(SocketAddress&);
+#endif
+
+ /** Get peer addresses of an association. */
+ int getpaddrs(sctp_assoc_t id,std::list<std::string>&);
+ /** Get all bound addresses of an association. */
+ int getladdrs(sctp_assoc_t id,std::list<std::string>&);
+
+ /** sctp_peeloff */
+ int PeelOff(sctp_assoc_t id);
+
+ /** recvmsg callback */
+ virtual void OnReceiveMessage(const char *buf,size_t sz,struct sockaddr *sa,socklen_t sa_len,struct sctp_sndrcvinfo *sinfo,int msg_flags) = 0;
+
+ void OnOptions(int,int,int,SOCKET) {}
+
+ virtual int Protocol();
+
+protected:
+ SctpSocket(const SctpSocket& s) : StreamSocket(s) {}
+ void OnRead();
+ void OnWrite();
+
+private:
+ SctpSocket& operator=(const SctpSocket& s) { return *this; }
+ int m_type; ///< SCTP_STREAM or SCTP_SEQPACKET
+ char *m_buf; ///< Temporary receive buffer
+};
+
+
+#ifdef SOCKETS_NAMESPACE
+} // namespace SOCKETS_NAMESPACE
+#endif
+
+#endif // USE_SCTP
+#endif // _SOCKETS_SctpSocket_H
+
diff --git a/Sockets/Semaphore.cpp b/Sockets/Semaphore.cpp
new file mode 100644
index 0000000..93cefc7
--- /dev/null
+++ b/Sockets/Semaphore.cpp
@@ -0,0 +1,76 @@
+/**
+ ** \file Semaphore.cpp
+ ** \date 2007-04-13
+ ** \author grymse@alhem.net
+**/
+/*
+Copyright (C) 2007 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.
+*/
+#include "Semaphore.h"
+
+
+#ifdef SOCKETS_NAMESPACE
+namespace SOCKETS_NAMESPACE {
+#endif
+
+
+Semaphore::Semaphore()
+{
+ sem_init(&m_sem, 0, 0);
+}
+
+
+Semaphore::Semaphore(unsigned int start_val)
+{
+ sem_init(&m_sem, 0, start_val);
+}
+
+
+Semaphore::~Semaphore()
+{
+ sem_destroy(&m_sem);
+}
+
+
+int Semaphore::Post()
+{
+ return sem_post(&m_sem);
+}
+
+
+int Semaphore::Wait()
+{
+ return sem_wait(&m_sem);
+}
+
+
+int Semaphore::TryWait()
+{
+ return sem_trywait(&m_sem);
+}
+
+
+int Semaphore::GetValue(int& i)
+{
+ return sem_getvalue(&m_sem, &i);
+}
+
+
+#ifdef SOCKETS_NAMESPACE
+} // namespace SOCKETS_NAMESPACE {
+#endif
+
diff --git a/Sockets/Semaphore.h b/Sockets/Semaphore.h
new file mode 100644
index 0000000..acafea4
--- /dev/null
+++ b/Sockets/Semaphore.h
@@ -0,0 +1,67 @@
+/**
+ ** \file Semaphore.h
+ ** \date 2007-04-13
+ ** \author grymse@alhem.net
+**/
+/*
+Copyright (C) 2007 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.
+*/
+#ifndef _SOCKETS_Semaphore_H
+#define _SOCKETS_Semaphore_H
+
+#include "sockets-config.h"
+#include <pthread.h>
+#ifdef MACOSX
+#include <sys/semaphore.h>
+#else
+#include <semaphore.h>
+#endif
+
+
+#ifdef SOCKETS_NAMESPACE
+namespace SOCKETS_NAMESPACE {
+#endif
+
+
+/** pthread semaphore wrapper.
+ \ingroup threading */
+class Semaphore
+{
+public:
+ Semaphore();
+ Semaphore(unsigned int start_val);
+ ~Semaphore();
+
+ int Post();
+ int Wait();
+ int TryWait();
+ int GetValue(int&);
+
+private:
+ Semaphore(const Semaphore& ) {} // copy constructor
+ Semaphore& operator=(const Semaphore& ) { return *this; } // assignment operator
+ sem_t m_sem;
+};
+
+
+
+
+#ifdef SOCKETS_NAMESPACE
+} // namespace SOCKETS_NAMESPACE {
+#endif
+#endif // _SOCKETS_Semaphore_H
+
diff --git a/Sockets/SmtpdSocket.cpp b/Sockets/SmtpdSocket.cpp
new file mode 100644
index 0000000..0d62925
--- /dev/null
+++ b/Sockets/SmtpdSocket.cpp
@@ -0,0 +1,234 @@
+/**
+ ** \file SmtpdSocket.cpp
+ ** \date 2007-05-10
+ ** \author grymse@alhem.net
+**/
+/*
+Copyright (C) 2007 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.
+*/
+#include "SmtpdSocket.h"
+#include "Parse.h"
+#include "Utility.h"
+
+#ifdef SOCKETS_NAMESPACE
+namespace SOCKETS_NAMESPACE {
+#endif
+
+SmtpdSocket::SmtpdSocket(ISocketHandler& h)
+:TcpSocket(h)
+,m_hello(false)
+,m_data(false)
+,m_header(false)
+{
+ SetLineProtocol();
+}
+
+
+void SmtpdSocket::OnAccept()
+{
+ Send("220 ESMTP; \r\n");
+}
+
+
+void SmtpdSocket::OnLine(const std::string& line)
+{
+ if (m_data)
+ {
+ if (m_header)
+ {
+ if (!line.size())
+ {
+ if (m_header_line.size())
+ {
+ Parse pa(m_header_line, ":");
+ std::string key = pa.getword();
+ OnHeader(key, pa.getrest());
+ }
+ m_header = false;
+ OnHeaderComplete();
+ }
+ else
+ if (line[0] == ' ' || line[0] == '\t')
+ {
+ m_header_line += line;
+ }
+ else
+ {
+ if (m_header_line.size())
+ {
+ Parse pa(m_header_line, ":");
+ std::string key = pa.getword();
+ OnHeader(key, pa.getrest());
+ }
+ m_header_line = line;
+ }
+ }
+ else
+ if (line == ".")
+ {
+ m_data = false;
+ if (OnDataComplete())
+ Send("250 OK\r\n");
+ else
+ Send("550 Failed\r\n");
+ }
+ else
+ if (line.size() && line[0] == '.')
+ {
+ OnData(line.substr(1));
+ }
+ else
+ {
+ OnData(line);
+ }
+ return;
+ }
+ Parse pa(line);
+ std::string cmd = Utility::ToUpper(pa.getword());
+
+ if (cmd == "EHLO")
+ {
+ if (!OnHello(pa.getrest()))
+ {
+ Send("550 Failed\r\n");
+ }
+ else
+ {
+ m_hello = true;
+ Send("250 mail.alhem.net\r\n");
+ }
+ }
+ else
+ if (cmd == "HELO")
+ {
+ if (!OnHello(pa.getrest()))
+ {
+ Send("550 Failed\r\n");
+ }
+ else
+ {
+ m_hello = true;
+ Send("250 mail.alhem.net\r\n");
+ }
+ }
+ else
+ if (!m_hello)
+ {
+ OnAbort(SMTP_NO_HELLO);
+ SetCloseAndDelete();
+ }
+ else
+ if (cmd == "MAIL") // mail from:
+ {
+ Parse pa(line, ":");
+ pa.getword(); // 'mail'
+ pa.getword(); // 'from'
+ std::string email = Utility::ToLower(pa.getrest());
+
+ EmailAddress addr( email );
+ if (addr.GetName().size() > 64)
+ {
+ OnAbort(SMTP_NAME_TOO_LONG);
+ Send("500 Name too long.\r\n");
+ return;
+ }
+ if (addr.GetDomain().size() > 64)
+ {
+ OnAbort(SMTP_DOMAIN_TOO_LONG);
+ Send("500 Domain too long.\r\n");
+ return;
+ }
+
+ if (!OnMailFrom( addr ))
+ {
+ Send("550 Failed\r\n");
+ }
+ else
+ {
+ Send("250 OK\r\n");
+ }
+ }
+ else
+ if (cmd == "RCPT") // rcpt to:
+ {
+ Parse pa(line, ":");
+ pa.getword(); // 'rcpt'
+ pa.getword(); // 'to'
+ std::string email = Utility::ToLower(pa.getrest());
+ // %! reject based on user / domain?
+ EmailAddress addr( email );
+
+ if (addr.GetName().size() > 64)
+ {
+ OnAbort(SMTP_NAME_TOO_LONG);
+ Send("500 Name too long.\r\n");
+ return;
+ }
+ if (addr.GetDomain().size() > 64)
+ {
+ OnAbort(SMTP_DOMAIN_TOO_LONG);
+ Send("500 Domain too long.\r\n");
+ return;
+ }
+
+ if (!OnRcptTo( addr ))
+ {
+ Send("553 Failed\r\n");
+ }
+ else
+ {
+ Send("250 OK\r\n");
+ }
+ }
+ else
+ if (cmd == "DATA")
+ {
+ Send("354 Enter mail, end with \".\" on a line by itself\r\n");
+ m_data = true;
+ m_header = false;
+ }
+ else
+ if (cmd == "RSET")
+ {
+ m_data = false;
+ m_header = false;
+ OnRset();
+ Send("250 OK\r\n"); // %! ???
+ }
+ else
+ if (cmd == "QUIT")
+ {
+ OnAbort(SMTP_QUIT);
+ Send("221 Bye Bye\r\n");
+ SetCloseAndDelete();
+ }
+ else
+ if (cmd == "NOOP")
+ {
+ Send("250 OK\r\n");
+ }
+ else
+ {
+ OnNotSupported(cmd, pa.getrest());
+ }
+}
+
+
+#ifdef SOCKETS_NAMESPACE
+} // namespace SOCKETS_NAMESPACE {
+#endif
+
diff --git a/Sockets/SmtpdSocket.h b/Sockets/SmtpdSocket.h
new file mode 100644
index 0000000..d884d05
--- /dev/null
+++ b/Sockets/SmtpdSocket.h
@@ -0,0 +1,143 @@
+/**
+ ** \file SmtpdSocket.h
+ ** \date 2007-05-10
+ ** \author grymse@alhem.net
+**/
+/*
+Copyright (C) 2007 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.
+*/
+#ifndef _SOCKETS_SmtpdSocket_H
+#define _SOCKETS_SmtpdSocket_H
+
+#include "sockets-config.h"
+#include <string>
+#include "TcpSocket.h"
+
+#ifdef SOCKETS_NAMESPACE
+namespace SOCKETS_NAMESPACE {
+#endif
+
+
+/** Smtp server base class. */
+class SmtpdSocket : public TcpSocket
+{
+protected:
+ typedef enum {
+ SMTP_NO_HELLO,
+ SMTP_NAME_TOO_LONG,
+ SMTP_DOMAIN_TOO_LONG,
+ SMTP_QUIT
+ } reason_t;
+
+public:
+ class EmailAddress {
+ public:
+ EmailAddress(const std::string& str_in)
+ {
+ std::string str = str_in;
+ size_t i = str.find("<");
+ if (i != std::string::npos)
+ str = str.substr(i + 1);
+ i = str.find("@");
+ if (i != std::string::npos)
+ {
+ m_name = str.substr(0, i);
+ str = str.substr(i + 1);
+ i = str.find(">");
+ if (i != std::string::npos)
+ str = str.substr(0, i);
+ m_domain = str;
+ }
+ while (m_name.size() && m_name[m_name.size() - 1] == ' ')
+ m_name.resize(m_name.size() - 1);
+ while (m_domain.size() && m_domain[m_domain.size() - 1] == ' ')
+ m_domain.resize(m_domain.size() - 1);
+ while (m_name.size() && m_name[0] == ' ')
+ m_name = m_name.substr(1);
+ while (m_domain.size() && m_domain[0] == ' ')
+ m_domain = m_domain.substr(1);
+ m_top = m_domain;
+ {
+ for (size_t i = 0; i < m_domain.size(); i++)
+ {
+ if (m_domain[i] == '.')
+ {
+ m_sub = m_top;
+ m_top = m_domain.substr(i + 1);
+ }
+ }
+ }
+ }
+
+ const std::string& GetName() const { return m_name; }
+ const std::string& GetDomain() const { return m_domain; }
+ const std::string& GetTopDomain() const { return m_top; }
+ const std::string& GetSubDomain() const { return m_sub; }
+
+ std::string ToString() const { return m_name + "@" + m_domain; }
+
+ private:
+ std::string m_name;
+ std::string m_domain;
+ std::string m_top;
+ std::string m_sub;
+ };
+
+public:
+ SmtpdSocket(ISocketHandler&);
+
+ void OnAccept();
+ void OnLine(const std::string&);
+
+ /** \return 'false' to abort */
+ virtual bool OnHello(const std::string& domain) = 0;
+
+ /** \return 'false' to abort */
+ virtual bool OnMailFrom(const EmailAddress& addr) = 0;
+
+ /** \return 'false' to abort */
+ virtual bool OnRcptTo(const EmailAddress& addr) = 0;
+
+ virtual void OnHeader(const std::string& key, const std::string& value) = 0;
+
+ virtual void OnHeaderComplete() = 0;
+
+ virtual void OnData(const std::string& line) = 0;
+
+ /** \return 'false' if message write failed (message will probably be resent) */
+ virtual bool OnDataComplete() = 0;
+
+ virtual void OnRset() = 0;
+
+ virtual void OnAbort(reason_t) = 0;
+
+ virtual void OnNotSupported(const std::string& cmd, const std::string& arg) = 0;
+
+private:
+ bool m_hello; // we need HELO or EHLO first of all
+ bool m_data;
+ bool m_header;
+ std::string m_header_line;
+};
+
+
+#ifdef SOCKETS_NAMESPACE
+} // namespace SOCKETS_NAMESPACE {
+#endif
+
+#endif // _SOCKETS_SmtpdSocket_H
+
diff --git a/Sockets/Socket.cpp b/Sockets/Socket.cpp
new file mode 100644
index 0000000..42d2c23
--- /dev/null
+++ b/Sockets/Socket.cpp
@@ -0,0 +1,1896 @@
+/** \file Socket.cpp
+ ** \date 2004-02-13
+ ** \author grymse@alhem.net
+**/
+/*
+Copyright (C) 2004-2007 Anders Hedstrom
+
+This library is made available under the terms of the GNU GPL.
+
+If you would like to use this library in a closed-source application,
+a separate license agreement is available. For information about
+the closed-source license agreement for the C++ sockets library,
+please visit http://www.alhem.net/Sockets/license.html and/or
+email license@alhem.net.
+
+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.
+*/
+#include "Socket.h"
+#ifdef _WIN32
+#ifdef _MSC_VER
+#pragma warning(disable:4786)
+#endif
+#include <stdlib.h>
+#else
+#include <errno.h>
+#include <netdb.h>
+#endif
+#include <ctype.h>
+#include <fcntl.h>
+
+#include "ISocketHandler.h"
+#include "Utility.h"
+
+#include "SocketAddress.h"
+#include "SocketHandler.h"
+#ifdef ENABLE_EXCEPTIONS
+#include "Exception.h"
+#endif
+#include "Ipv4Address.h"
+
+#ifdef _DEBUG
+#define DEB(x) x; fflush(stderr);
+#else
+#define DEB(x)
+#endif
+
+#ifdef SOCKETS_NAMESPACE
+namespace SOCKETS_NAMESPACE {
+#endif
+
+
+// statics
+#ifdef _WIN32
+WSAInitializer Socket::m_winsock_init;
+#endif
+
+
+Socket::Socket(ISocketHandler& h)
+//:m_flags(0)
+:m_handler(h)
+,m_socket( INVALID_SOCKET )
+,m_bDel(false)
+,m_bClose(false)
+,m_tCreate(time(NULL))
+,m_parent(NULL)
+,m_b_disable_read(false)
+,m_connected(false)
+,m_b_erased_by_handler(false)
+,m_tClose(0)
+,m_client_remote_address(NULL)
+,m_remote_address(NULL)
+,m_traffic_monitor(NULL)
+#ifdef HAVE_OPENSSL
+,m_b_enable_ssl(false)
+,m_b_ssl(false)
+,m_b_ssl_server(false)
+#endif
+#ifdef ENABLE_IPV6
+,m_ipv6(false)
+#endif
+#ifdef ENABLE_POOL
+,m_socket_type(0)
+,m_bClient(false)
+,m_bRetain(false)
+,m_bLost(false)
+#endif
+#ifdef ENABLE_SOCKS4
+,m_bSocks4(false)
+,m_socks4_host(h.GetSocks4Host())
+,m_socks4_port(h.GetSocks4Port())
+,m_socks4_userid(h.GetSocks4Userid())
+#endif
+#ifdef ENABLE_DETACH
+,m_detach(false)
+,m_detached(false)
+,m_pThread(NULL)
+,m_slave_handler(NULL)
+#endif
+{
+}
+
+
+Socket::~Socket()
+{
+ Handler().Remove(this);
+ if (m_socket != INVALID_SOCKET
+#ifdef ENABLE_POOL
+ && !m_bRetain
+#endif
+ )
+ {
+ Close();
+ }
+}
+
+
+void Socket::Init()
+{
+}
+
+
+void Socket::OnRead()
+{
+}
+
+
+void Socket::OnWrite()
+{
+}
+
+
+void Socket::OnException()
+{
+ // %! exception doesn't always mean something bad happened, this code should be reworked
+ // errno valid here?
+ int err = SoError();
+ Handler().LogError(this, "exception on select", err, StrError(err), LOG_LEVEL_FATAL);
+ SetCloseAndDelete();
+}
+
+
+void Socket::OnDelete()
+{
+}
+
+
+void Socket::OnConnect()
+{
+}
+
+
+void Socket::OnAccept()
+{
+}
+
+
+int Socket::Close()
+{
+ if (m_socket == INVALID_SOCKET) // this could happen
+ {
+ Handler().LogError(this, "Socket::Close", 0, "file descriptor invalid", LOG_LEVEL_WARNING);
+ return 0;
+ }
+ int n;
+ if ((n = closesocket(m_socket)) == -1)
+ {
+ // failed...
+ Handler().LogError(this, "close", Errno, StrError(Errno), LOG_LEVEL_ERROR);
+ }
+ Handler().Set(m_socket, false, false, false); // remove from fd_set's
+ Handler().AddList(m_socket, LIST_CALLONCONNECT, false);
+#ifdef ENABLE_DETACH
+ Handler().AddList(m_socket, LIST_DETACH, false);
+#endif
+ Handler().AddList(m_socket, LIST_TIMEOUT, false);
+ Handler().AddList(m_socket, LIST_RETRY, false);
+ Handler().AddList(m_socket, LIST_CLOSE, false);
+ m_socket = INVALID_SOCKET;
+ return n;
+}
+
+
+SOCKET Socket::CreateSocket(int af,int type, const std::string& protocol)
+{
+ struct protoent *p = NULL;
+ SOCKET s;
+
+#ifdef ENABLE_POOL
+ m_socket_type = type;
+ m_socket_protocol = protocol;
+#endif
+ if (protocol.size())
+ {
+ p = getprotobyname( protocol.c_str() );
+ if (!p)
+ {
+ Handler().LogError(this, "getprotobyname", Errno, StrError(Errno), LOG_LEVEL_FATAL);
+ SetCloseAndDelete();
+#ifdef ENABLE_EXCEPTIONS
+ throw Exception(std::string("getprotobyname() failed: ") + StrError(Errno));
+#endif
+ return INVALID_SOCKET;
+ }
+ }
+ int protno = p ? p -> p_proto : 0;
+
+ s = socket(af, type, protno);
+ if (s == INVALID_SOCKET)
+ {
+ Handler().LogError(this, "socket", Errno, StrError(Errno), LOG_LEVEL_FATAL);
+ SetCloseAndDelete();
+#ifdef ENABLE_EXCEPTIONS
+ throw Exception(std::string("socket() failed: ") + StrError(Errno));
+#endif
+ return INVALID_SOCKET;
+ }
+ Attach(s);
+ OnOptions(af, type, protno, s);
+ Attach(INVALID_SOCKET);
+ return s;
+}
+
+
+void Socket::Attach(SOCKET s)
+{
+ m_socket = s;
+}
+
+
+SOCKET Socket::GetSocket()
+{
+ return m_socket;
+}
+
+
+void Socket::SetDeleteByHandler(bool x)
+{
+ m_bDel = x;
+}
+
+
+bool Socket::DeleteByHandler()
+{
+ return m_bDel;
+}
+
+
+void Socket::SetCloseAndDelete(bool x)
+{
+ if (x != m_bClose)
+ {
+ Handler().AddList(m_socket, LIST_CLOSE, x);
+ m_bClose = x;
+ if (x)
+ {
+ m_tClose = time(NULL);
+ }
+ }
+}
+
+
+bool Socket::CloseAndDelete()
+{
+ return m_bClose;
+}
+
+
+void Socket::SetRemoteAddress(SocketAddress& ad) //struct sockaddr* sa, socklen_t l)
+{
+ m_remote_address = ad.GetCopy();
+}
+
+
+std::auto_ptr<SocketAddress> Socket::GetRemoteSocketAddress()
+{
+ return std::auto_ptr<SocketAddress>(m_remote_address -> GetCopy());
+}
+
+
+ISocketHandler& Socket::Handler() const
+{
+#ifdef ENABLE_DETACH
+ if (IsDetached())
+ return *m_slave_handler;
+#endif
+ return m_handler;
+}
+
+
+ISocketHandler& Socket::MasterHandler() const
+{
+ return m_handler;
+}
+
+
+ipaddr_t Socket::GetRemoteIP4()
+{
+ ipaddr_t l = 0;
+#ifdef ENABLE_IPV6
+ if (m_ipv6)
+ {
+ Handler().LogError(this, "GetRemoteIP4", 0, "get ipv4 address for ipv6 socket", LOG_LEVEL_WARNING);
+ }
+#endif
+ if (m_remote_address.get() != NULL)
+ {
+ struct sockaddr *p = *m_remote_address;
+ struct sockaddr_in *sa = (struct sockaddr_in *)p;
+ memcpy(&l, &sa -> sin_addr, sizeof(struct in_addr));
+ }
+ return l;
+}
+
+
+#ifdef ENABLE_IPV6
+#ifdef IPPROTO_IPV6
+struct in6_addr Socket::GetRemoteIP6()
+{
+ if (!m_ipv6)
+ {
+ Handler().LogError(this, "GetRemoteIP6", 0, "get ipv6 address for ipv4 socket", LOG_LEVEL_WARNING);
+ }
+ struct sockaddr_in6 fail;
+ if (m_remote_address.get() != NULL)
+ {
+ struct sockaddr *p = *m_remote_address;
+ memcpy(&fail, p, sizeof(struct sockaddr_in6));
+ }
+ else
+ {
+ memset(&fail, 0, sizeof(struct sockaddr_in6));
+ }
+ return fail.sin6_addr;
+}
+#endif
+#endif
+
+
+port_t Socket::GetRemotePort()
+{
+ if (!m_remote_address.get())
+ {
+ return 0;
+ }
+ return m_remote_address -> GetPort();
+}
+
+
+std::string Socket::GetRemoteAddress()
+{
+ if (!m_remote_address.get())
+ {
+ return "";
+ }
+ return m_remote_address -> Convert(false);
+}
+
+
+std::string Socket::GetRemoteHostname()
+{
+ if (!m_remote_address.get())
+ {
+ return "";
+ }
+ return m_remote_address -> Reverse();
+}
+
+
+bool Socket::SetNonblocking(bool bNb)
+{
+#ifdef _WIN32
+ unsigned long l = bNb ? 1 : 0;
+ int n = ioctlsocket(m_socket, FIONBIO, &l);
+ if (n != 0)
+ {
+ Handler().LogError(this, "ioctlsocket(FIONBIO)", Errno, "");
+ return false;
+ }
+ return true;
+#else
+ if (bNb)
+ {
+ if (fcntl(m_socket, F_SETFL, O_NONBLOCK) == -1)
+ {
+ Handler().LogError(this, "fcntl(F_SETFL, O_NONBLOCK)", Errno, StrError(Errno), LOG_LEVEL_ERROR);
+ return false;
+ }
+ }
+ else
+ {
+ if (fcntl(m_socket, F_SETFL, 0) == -1)
+ {
+ Handler().LogError(this, "fcntl(F_SETFL, 0)", Errno, StrError(Errno), LOG_LEVEL_ERROR);
+ return false;
+ }
+ }
+ return true;
+#endif
+}
+
+
+bool Socket::SetNonblocking(bool bNb, SOCKET s)
+{
+#ifdef _WIN32
+ unsigned long l = bNb ? 1 : 0;
+ int n = ioctlsocket(s, FIONBIO, &l);
+ if (n != 0)
+ {
+ Handler().LogError(this, "ioctlsocket(FIONBIO)", Errno, "");
+ return false;
+ }
+ return true;
+#else
+ if (bNb)
+ {
+ if (fcntl(s, F_SETFL, O_NONBLOCK) == -1)
+ {
+ Handler().LogError(this, "fcntl(F_SETFL, O_NONBLOCK)", Errno, StrError(Errno), LOG_LEVEL_ERROR);
+ return false;
+ }
+ }
+ else
+ {
+ if (fcntl(s, F_SETFL, 0) == -1)
+ {
+ Handler().LogError(this, "fcntl(F_SETFL, 0)", Errno, StrError(Errno), LOG_LEVEL_ERROR);
+ return false;
+ }
+ }
+ return true;
+#endif
+}
+
+
+void Socket::Set(bool bRead, bool bWrite, bool bException)
+{
+ Handler().Set(m_socket, bRead, bWrite, bException);
+}
+
+
+bool Socket::Ready()
+{
+ if (m_socket != INVALID_SOCKET && !CloseAndDelete())
+ return true;
+ return false;
+}
+
+
+void Socket::OnLine(const std::string& )
+{
+}
+
+
+void Socket::OnConnectFailed()
+{
+}
+
+
+Socket *Socket::GetParent()
+{
+ return m_parent;
+}
+
+
+void Socket::SetParent(Socket *x)
+{
+ m_parent = x;
+}
+
+
+port_t Socket::GetPort()
+{
+ Handler().LogError(this, "GetPort", 0, "GetPort only implemented for ListenSocket", LOG_LEVEL_WARNING);
+ return 0;
+}
+
+
+bool Socket::OnConnectRetry()
+{
+ return true;
+}
+
+
+#ifdef ENABLE_RECONNECT
+void Socket::OnReconnect()
+{
+}
+#endif
+
+
+time_t Socket::Uptime()
+{
+ return time(NULL) - m_tCreate;
+}
+
+
+#ifdef ENABLE_IPV6
+void Socket::SetIpv6(bool x)
+{
+ m_ipv6 = x;
+}
+
+
+bool Socket::IsIpv6()
+{
+ return m_ipv6;
+}
+#endif
+
+
+void Socket::DisableRead(bool x)
+{
+ m_b_disable_read = x;
+}
+
+
+bool Socket::IsDisableRead()
+{
+ return m_b_disable_read;
+}
+
+
+void Socket::SendBuf(const char *,size_t,int)
+{
+}
+
+
+void Socket::Send(const std::string&,int)
+{
+}
+
+
+void Socket::SetConnected(bool x)
+{
+ m_connected = x;
+}
+
+
+bool Socket::IsConnected()
+{
+ return m_connected;
+}
+
+
+void Socket::OnDisconnect()
+{
+}
+
+
+void Socket::SetErasedByHandler(bool x)
+{
+ m_b_erased_by_handler = x;
+}
+
+
+bool Socket::ErasedByHandler()
+{
+ return m_b_erased_by_handler;
+}
+
+
+time_t Socket::TimeSinceClose()
+{
+ return time(NULL) - m_tClose;
+}
+
+
+void Socket::SetClientRemoteAddress(SocketAddress& ad)
+{
+ if (!ad.IsValid())
+ {
+ Handler().LogError(this, "SetClientRemoteAddress", 0, "remote address not valid", LOG_LEVEL_ERROR);
+ }
+ m_client_remote_address = ad.GetCopy();
+}
+
+
+std::auto_ptr<SocketAddress> Socket::GetClientRemoteAddress()
+{
+ if (!m_client_remote_address.get())
+ {
+ Handler().LogError(this, "GetClientRemoteAddress", 0, "remote address not yet set", LOG_LEVEL_ERROR);
+ }
+ return std::auto_ptr<SocketAddress>(m_client_remote_address -> GetCopy());
+}
+
+
+uint64_t Socket::GetBytesSent(bool)
+{
+ return 0;
+}
+
+
+uint64_t Socket::GetBytesReceived(bool)
+{
+ return 0;
+}
+
+
+#ifdef HAVE_OPENSSL
+void Socket::OnSSLConnect()
+{
+}
+
+
+void Socket::OnSSLAccept()
+{
+}
+
+
+bool Socket::SSLNegotiate()
+{
+ return false;
+}
+
+
+bool Socket::IsSSL()
+{
+ return m_b_enable_ssl;
+}
+
+
+void Socket::EnableSSL(bool x)
+{
+ m_b_enable_ssl = x;
+}
+
+
+bool Socket::IsSSLNegotiate()
+{
+ return m_b_ssl;
+}
+
+
+void Socket::SetSSLNegotiate(bool x)
+{
+ m_b_ssl = x;
+}
+
+
+bool Socket::IsSSLServer()
+{
+ return m_b_ssl_server;
+}
+
+
+void Socket::SetSSLServer(bool x)
+{
+ m_b_ssl_server = x;
+}
+
+
+void Socket::OnSSLConnectFailed()
+{
+}
+
+
+void Socket::OnSSLAcceptFailed()
+{
+}
+#endif // HAVE_OPENSSL
+
+
+#ifdef ENABLE_POOL
+void Socket::CopyConnection(Socket *sock)
+{
+ Attach( sock -> GetSocket() );
+#ifdef ENABLE_IPV6
+ SetIpv6( sock -> IsIpv6() );
+#endif
+ SetSocketType( sock -> GetSocketType() );
+ SetSocketProtocol( sock -> GetSocketProtocol() );
+
+ SetClientRemoteAddress( *sock -> GetClientRemoteAddress() );
+ SetRemoteAddress( *sock -> GetRemoteSocketAddress() );
+}
+
+
+void Socket::SetIsClient()
+{
+ m_bClient = true;
+}
+
+
+void Socket::SetSocketType(int x)
+{
+ m_socket_type = x;
+}
+
+
+int Socket::GetSocketType()
+{
+ return m_socket_type;
+}
+
+
+void Socket::SetSocketProtocol(const std::string& x)
+{
+ m_socket_protocol = x;
+}
+
+
+const std::string& Socket::GetSocketProtocol()
+{
+ return m_socket_protocol;
+}
+
+
+void Socket::SetRetain()
+{
+ if (m_bClient) m_bRetain = true;
+}
+
+
+bool Socket::Retain()
+{
+ return m_bRetain;
+}
+
+
+void Socket::SetLost()
+{
+ m_bLost = true;
+}
+
+
+bool Socket::Lost()
+{
+ return m_bLost;
+}
+#endif // ENABLE_POOL
+
+
+#ifdef ENABLE_SOCKS4
+void Socket::OnSocks4Connect()
+{
+ Handler().LogError(this, "OnSocks4Connect", 0, "Use with TcpSocket only");
+}
+
+
+void Socket::OnSocks4ConnectFailed()
+{
+ Handler().LogError(this, "OnSocks4ConnectFailed", 0, "Use with TcpSocket only");
+}
+
+
+bool Socket::OnSocks4Read()
+{
+ Handler().LogError(this, "OnSocks4Read", 0, "Use with TcpSocket only");
+ return true;
+}
+
+
+void Socket::SetSocks4Host(const std::string& host)
+{
+ Utility::u2ip(host, m_socks4_host);
+}
+
+
+bool Socket::Socks4()
+{
+ return m_bSocks4;
+}
+
+
+void Socket::SetSocks4(bool x)
+{
+ m_bSocks4 = x;
+}
+
+
+void Socket::SetSocks4Host(ipaddr_t a)
+{
+ m_socks4_host = a;
+}
+
+
+void Socket::SetSocks4Port(port_t p)
+{
+ m_socks4_port = p;
+}
+
+
+void Socket::SetSocks4Userid(const std::string& x)
+{
+ m_socks4_userid = x;
+}
+
+
+ipaddr_t Socket::GetSocks4Host()
+{
+ return m_socks4_host;
+}
+
+
+port_t Socket::GetSocks4Port()
+{
+ return m_socks4_port;
+}
+
+
+const std::string& Socket::GetSocks4Userid()
+{
+ return m_socks4_userid;
+}
+#endif // ENABLE_SOCKS4
+
+
+#ifdef ENABLE_DETACH
+bool Socket::Detach()
+{
+ if (!DeleteByHandler())
+ return false;
+ if (m_pThread)
+ return false;
+ if (m_detached)
+ return false;
+ SetDetach();
+ return true;
+}
+
+
+void Socket::DetachSocket()
+{
+ SetDetached();
+ m_pThread = new SocketThread(this);
+ m_pThread -> SetRelease(true);
+}
+
+
+void Socket::OnDetached()
+{
+}
+
+
+void Socket::SetDetach(bool x)
+{
+ Handler().AddList(m_socket, LIST_DETACH, x);
+ m_detach = x;
+}
+
+
+bool Socket::IsDetach()
+{
+ return m_detach;
+}
+
+
+void Socket::SetDetached(bool x)
+{
+ m_detached = x;
+}
+
+
+const bool Socket::IsDetached() const
+{
+ return m_detached;
+}
+
+
+void Socket::SetSlaveHandler(ISocketHandler *p)
+{
+ m_slave_handler = p;
+}
+
+
+Socket::SocketThread::SocketThread(Socket *p)
+:Thread(false)
+,m_socket(p)
+{
+ // Creator will release
+}
+
+
+Socket::SocketThread::~SocketThread()
+{
+ if (IsRunning())
+ {
+ SetRelease(true);
+ SetRunning(false);
+#ifdef _WIN32
+ Sleep(1000);
+#else
+ sleep(1);
+#endif
+ }
+}
+
+
+void Socket::SocketThread::Run()
+{
+ SocketHandler h;
+ h.SetSlave();
+ h.Add(m_socket);
+ m_socket -> SetSlaveHandler(&h);
+ m_socket -> OnDetached();
+ while (h.GetCount() && IsRunning())
+ {
+ h.Select(0, 500000);
+ }
+ // m_socket now deleted oops
+ // yeah oops m_socket delete its socket thread, that means this
+ // so Socket will no longer delete its socket thread, instead we do this:
+ SetDeleteOnExit();
+}
+#endif // ENABLE_DETACH
+
+
+#ifdef ENABLE_RESOLVER
+int Socket::Resolve(const std::string& host,port_t port)
+{
+ return Handler().Resolve(this, host, port);
+}
+
+
+#ifdef ENABLE_IPV6
+int Socket::Resolve6(const std::string& host,port_t port)
+{
+ return Handler().Resolve6(this, host, port);
+}
+#endif
+
+
+int Socket::Resolve(ipaddr_t a)
+{
+ return Handler().Resolve(this, a);
+}
+
+
+#ifdef ENABLE_IPV6
+int Socket::Resolve(in6_addr& a)
+{
+ return Handler().Resolve(this, a);
+}
+#endif
+
+
+void Socket::OnResolved(int,ipaddr_t,port_t)
+{
+}
+
+
+#ifdef ENABLE_IPV6
+void Socket::OnResolved(int,in6_addr&,port_t)
+{
+}
+#endif
+
+
+void Socket::OnReverseResolved(int,const std::string&)
+{
+}
+
+
+void Socket::OnResolveFailed(int)
+{
+}
+#endif // ENABLE_RESOLVER
+
+
+/* IP options */
+
+
+bool Socket::SetIpOptions(const void *p, socklen_t len)
+{
+#ifdef IP_OPTIONS
+ if (setsockopt(GetSocket(), IPPROTO_IP, IP_OPTIONS, (char *)p, len) == -1)
+ {
+ Handler().LogError(this, "setsockopt(IPPROTO_IP, IP_OPTIONS)", Errno, StrError(Errno), LOG_LEVEL_FATAL);
+ return false;
+ }
+ return true;
+#else
+ Handler().LogError(this, "ip option not available", 0, "IP_OPTIONS", LOG_LEVEL_INFO);
+ return false;
+#endif
+}
+
+
+#ifdef IP_PKTINFO
+bool Socket::SetIpPktinfo(bool x)
+{
+ int optval = x ? 1 : 0;
+ if (setsockopt(GetSocket(), IPPROTO_IP, IP_PKTINFO, (char *)&optval, sizeof(optval)) == -1)
+ {
+ Handler().LogError(this, "setsockopt(IPPROTO_IP, IP_PKTINFO)", Errno, StrError(Errno), LOG_LEVEL_FATAL);
+ return false;
+ }
+ return true;
+}
+#endif
+
+
+#ifdef IP_RECVTOS
+bool Socket::SetIpRecvTOS(bool x)
+{
+ int optval = x ? 1 : 0;
+ if (setsockopt(GetSocket(), IPPROTO_IP, IP_RECVTOS, (char *)&optval, sizeof(optval)) == -1)
+ {
+ Handler().LogError(this, "setsockopt(IPPROTO_IP, IP_RECVTOS)", Errno, StrError(Errno), LOG_LEVEL_FATAL);
+ return false;
+ }
+ return true;
+}
+#endif
+
+
+#ifdef IP_RECVTTL
+bool Socket::SetIpRecvTTL(bool x)
+{
+ int optval = x ? 1 : 0;
+ if (setsockopt(GetSocket(), IPPROTO_IP, IP_RECVTTL, (char *)&optval, sizeof(optval)) == -1)
+ {
+ Handler().LogError(this, "setsockopt(IPPROTO_IP, IP_RECVTTL)", Errno, StrError(Errno), LOG_LEVEL_FATAL);
+ return false;
+ }
+ return true;
+}
+#endif
+
+
+#ifdef IP_RECVOPTS
+bool Socket::SetIpRecvopts(bool x)
+{
+ int optval = x ? 1 : 0;
+ if (setsockopt(GetSocket(), IPPROTO_IP, IP_RECVOPTS, (char *)&optval, sizeof(optval)) == -1)
+ {
+ Handler().LogError(this, "setsockopt(IPPROTO_IP, IP_RECVOPTS)", Errno, StrError(Errno), LOG_LEVEL_FATAL);
+ return false;
+ }
+ return true;
+}
+#endif
+
+
+#ifdef IP_RETOPTS
+bool Socket::SetIpRetopts(bool x)
+{
+ int optval = x ? 1 : 0;
+ if (setsockopt(GetSocket(), IPPROTO_IP, IP_RETOPTS, (char *)&optval, sizeof(optval)) == -1)
+ {
+ Handler().LogError(this, "setsockopt(IPPROTO_IP, IP_RETOPTS)", Errno, StrError(Errno), LOG_LEVEL_FATAL);
+ return false;
+ }
+ return true;
+}
+#endif
+
+
+bool Socket::SetIpTOS(unsigned char tos)
+{
+#ifdef IP_TOS
+ if (setsockopt(GetSocket(), IPPROTO_IP, IP_TOS, (char *)&tos, sizeof(tos)) == -1)
+ {
+ Handler().LogError(this, "setsockopt(IPPROTO_IP, IP_TOS)", Errno, StrError(Errno), LOG_LEVEL_FATAL);
+ return false;
+ }
+ return true;
+#else
+ Handler().LogError(this, "ip option not available", 0, "IP_TOS", LOG_LEVEL_INFO);
+ return false;
+#endif
+}
+
+
+unsigned char Socket::IpTOS()
+{
+ unsigned char tos = 0;
+#ifdef IP_TOS
+ socklen_t len = sizeof(tos);
+ if (getsockopt(GetSocket(), IPPROTO_IP, IP_TOS, (char *)&tos, &len) == -1)
+ {
+ Handler().LogError(this, "setsockopt(IPPROTO_IP, IP_TOS)", Errno, StrError(Errno), LOG_LEVEL_FATAL);
+ }
+#else
+ Handler().LogError(this, "ip option not available", 0, "IP_TOS", LOG_LEVEL_INFO);
+#endif
+ return tos;
+}
+
+
+bool Socket::SetIpTTL(int ttl)
+{
+#ifdef IP_TTL
+ if (setsockopt(GetSocket(), IPPROTO_IP, IP_TTL, (char *)&ttl, sizeof(ttl)) == -1)
+ {
+ Handler().LogError(this, "setsockopt(IPPROTO_IP, IP_TTL)", Errno, StrError(Errno), LOG_LEVEL_FATAL);
+ return false;
+ }
+ return true;
+#else
+ Handler().LogError(this, "ip option not available", 0, "IP_TTL", LOG_LEVEL_INFO);
+ return false;
+#endif
+}
+
+
+int Socket::IpTTL()
+{
+ int ttl = 0;
+#ifdef IP_TTL
+ socklen_t len = sizeof(ttl);
+ if (getsockopt(GetSocket(), IPPROTO_IP, IP_TTL, (char *)&ttl, &len) == -1)
+ {
+ Handler().LogError(this, "setsockopt(IPPROTO_IP, IP_TTL)", Errno, StrError(Errno), LOG_LEVEL_FATAL);
+ }
+#else
+ Handler().LogError(this, "ip option not available", 0, "IP_TTL", LOG_LEVEL_INFO);
+#endif
+ return ttl;
+}
+
+
+bool Socket::SetIpHdrincl(bool x)
+{
+#ifdef IP_HDRINCL
+ int optval = x ? 1 : 0;
+ if (setsockopt(GetSocket(), IPPROTO_IP, IP_HDRINCL, (char *)&optval, sizeof(optval)) == -1)
+ {
+ Handler().LogError(this, "setsockopt(IPPROTO_IP, IP_HDRINCL)", Errno, StrError(Errno), LOG_LEVEL_FATAL);
+ return false;
+ }
+ return true;
+#else
+ Handler().LogError(this, "ip option not available", 0, "IP_HDRINCL", LOG_LEVEL_INFO);
+ return false;
+#endif
+}
+
+
+#ifdef IP_RECVERR
+bool Socket::SetIpRecverr(bool x)
+{
+ int optval = x ? 1 : 0;
+ if (setsockopt(GetSocket(), IPPROTO_IP, IP_RECVERR, (char *)&optval, sizeof(optval)) == -1)
+ {
+ Handler().LogError(this, "setsockopt(IPPROTO_IP, IP_RECVERR)", Errno, StrError(Errno), LOG_LEVEL_FATAL);
+ return false;
+ }
+ return true;
+}
+#endif
+
+
+#ifdef IP_MTU_DISCOVER
+bool Socket::SetIpMtudiscover(bool x)
+{
+ int optval = x ? 1 : 0;
+ if (setsockopt(GetSocket(), IPPROTO_IP, IP_MTU_DISCOVER, (char *)&optval, sizeof(optval)) == -1)
+ {
+ Handler().LogError(this, "setsockopt(IPPROTO_IP, IP_MTU_DISCOVER)", Errno, StrError(Errno), LOG_LEVEL_FATAL);
+ return false;
+ }
+ return true;
+}
+#endif
+
+
+#ifdef IP_MTU
+int Socket::IpMtu()
+{
+ int mtu = 0;
+ socklen_t len = sizeof(mtu);
+ if (getsockopt(GetSocket(), IPPROTO_IP, IP_MTU, (char *)&mtu, &len) == -1)
+ {
+ Handler().LogError(this, "setsockopt(IPPROTO_IP, IP_MTU)", Errno, StrError(Errno), LOG_LEVEL_FATAL);
+ }
+ return mtu;
+}
+#endif
+
+
+#ifdef IP_ROUTER_ALERT
+bool Socket::SetIpRouterAlert(bool x)
+{
+ int optval = x ? 1 : 0;
+ if (setsockopt(GetSocket(), IPPROTO_IP, IP_ROUTER_ALERT, (char *)&optval, sizeof(optval)) == -1)
+ {
+ Handler().LogError(this, "setsockopt(IPPROTO_IP, IP_ROUTER_ALERT)", Errno, StrError(Errno), LOG_LEVEL_FATAL);
+ return false;
+ }
+ return true;
+}
+#endif
+
+
+bool Socket::SetIpMulticastTTL(int ttl)
+{
+#ifdef IP_MULTICAST_TTL
+ if (setsockopt(GetSocket(), IPPROTO_IP, IP_MULTICAST_TTL, (char *)&ttl, sizeof(ttl)) == -1)
+ {
+ Handler().LogError(this, "setsockopt(IPPROTO_IP, IP_MULTICAST_TTL)", Errno, StrError(Errno), LOG_LEVEL_FATAL);
+ return false;
+ }
+ return true;
+#else
+ Handler().LogError(this, "ip option not available", 0, "IP_MULTICAST_TTL", LOG_LEVEL_INFO);
+ return false;
+#endif
+}
+
+
+int Socket::IpMulticastTTL()
+{
+ int ttl = 0;
+#ifdef IP_MULTICAST_TTL
+ socklen_t len = sizeof(ttl);
+ if (getsockopt(GetSocket(), IPPROTO_IP, IP_MULTICAST_TTL, (char *)&ttl, &len) == -1)
+ {
+ Handler().LogError(this, "setsockopt(IPPROTO_IP, IP_MULTICAST_TTL)", Errno, StrError(Errno), LOG_LEVEL_FATAL);
+ }
+#else
+ Handler().LogError(this, "ip option not available", 0, "IP_MULTICAST_TTL", LOG_LEVEL_INFO);
+#endif
+ return ttl;
+}
+
+
+bool Socket::SetMulticastLoop(bool x)
+{
+#ifdef IP_MULTICAST_LOOP
+ int optval = x ? 1 : 0;
+ if (setsockopt(GetSocket(), IPPROTO_IP, IP_MULTICAST_LOOP, (char *)&optval, sizeof(optval)) == -1)
+ {
+ Handler().LogError(this, "setsockopt(IPPROTO_IP, IP_MULTICAST_LOOP)", Errno, StrError(Errno), LOG_LEVEL_FATAL);
+ return false;
+ }
+ return true;
+#else
+ Handler().LogError(this, "ip option not available", 0, "IP_MULTICAST_LOOP", LOG_LEVEL_INFO);
+ return false;
+#endif
+}
+
+
+#ifdef LINUX
+bool Socket::IpAddMembership(struct ip_mreqn& ref)
+{
+#ifdef IP_ADD_MEMBERSHIP
+ if (setsockopt(GetSocket(), IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&ref, sizeof(struct ip_mreqn)) == -1)
+ {
+ Handler().LogError(this, "setsockopt(IPPROTO_IP, IP_ADD_MEMBERSHIP)", Errno, StrError(Errno), LOG_LEVEL_FATAL);
+ return false;
+ }
+ return true;
+#else
+ Handler().LogError(this, "ip option not available", 0, "IP_ADD_MEMBERSHIP", LOG_LEVEL_INFO);
+ return false;
+#endif
+}
+#endif
+
+
+bool Socket::IpAddMembership(struct ip_mreq& ref)
+{
+#ifdef IP_ADD_MEMBERSHIP
+ if (setsockopt(GetSocket(), IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&ref, sizeof(struct ip_mreq)) == -1)
+ {
+ Handler().LogError(this, "setsockopt(IPPROTO_IP, IP_ADD_MEMBERSHIP)", Errno, StrError(Errno), LOG_LEVEL_FATAL);
+ return false;
+ }
+ return true;
+#else
+ Handler().LogError(this, "ip option not available", 0, "IP_ADD_MEMBERSHIP", LOG_LEVEL_INFO);
+ return false;
+#endif
+}
+
+
+#ifdef LINUX
+bool Socket::IpDropMembership(struct ip_mreqn& ref)
+{
+#ifdef IP_DROP_MEMBERSHIP
+ if (setsockopt(GetSocket(), IPPROTO_IP, IP_DROP_MEMBERSHIP, (char *)&ref, sizeof(struct ip_mreqn)) == -1)
+ {
+ Handler().LogError(this, "setsockopt(IPPROTO_IP, IP_DROP_MEMBERSHIP)", Errno, StrError(Errno), LOG_LEVEL_FATAL);
+ return false;
+ }
+ return true;
+#else
+ Handler().LogError(this, "ip option not available", 0, "IP_DROP_MEMBERSHIP", LOG_LEVEL_INFO);
+ return false;
+#endif
+}
+#endif
+
+
+bool Socket::IpDropMembership(struct ip_mreq& ref)
+{
+#ifdef IP_DROP_MEMBERSHIP
+ if (setsockopt(GetSocket(), IPPROTO_IP, IP_DROP_MEMBERSHIP, (char *)&ref, sizeof(struct ip_mreq)) == -1)
+ {
+ Handler().LogError(this, "setsockopt(IPPROTO_IP, IP_DROP_MEMBERSHIP)", Errno, StrError(Errno), LOG_LEVEL_FATAL);
+ return false;
+ }
+ return true;
+#else
+ Handler().LogError(this, "ip option not available", 0, "IP_DROP_MEMBERSHIP", LOG_LEVEL_INFO);
+ return false;
+#endif
+}
+
+
+/* SOCKET options */
+
+
+bool Socket::SetSoReuseaddr(bool x)
+{
+#ifdef SO_REUSEADDR
+ int optval = x ? 1 : 0;
+ if (setsockopt(GetSocket(), SOL_SOCKET, SO_REUSEADDR, (char *)&optval, sizeof(optval)) == -1)
+ {
+ Handler().LogError(this, "setsockopt(SOL_SOCKET, SO_REUSEADDR)", Errno, StrError(Errno), LOG_LEVEL_FATAL);
+ return false;
+ }
+ return true;
+#else
+ Handler().LogError(this, "socket option not available", 0, "SO_REUSEADDR", LOG_LEVEL_INFO);
+ return false;
+#endif
+}
+
+
+bool Socket::SetSoKeepalive(bool x)
+{
+#ifdef SO_KEEPALIVE
+ int optval = x ? 1 : 0;
+ if (setsockopt(GetSocket(), SOL_SOCKET, SO_KEEPALIVE, (char *)&optval, sizeof(optval)) == -1)
+ {
+ Handler().LogError(this, "setsockopt(SOL_SOCKET, SO_KEEPALIVE)", Errno, StrError(Errno), LOG_LEVEL_FATAL);
+ return false;
+ }
+ return true;
+#else
+ Handler().LogError(this, "socket option not available", 0, "SO_KEEPALIVE", LOG_LEVEL_INFO);
+ return false;
+#endif
+}
+
+
+#ifdef SO_NOSIGPIPE
+bool Socket::SetSoNosigpipe(bool x)
+{
+ int optval = x ? 1 : 0;
+ if (setsockopt(GetSocket(), SOL_SOCKET, SO_NOSIGPIPE, (char *)&optval, sizeof(optval)) == -1)
+ {
+ Handler().LogError(this, "setsockopt(SOL_SOCKET, SO_NOSIGPIPE)", Errno, StrError(Errno), LOG_LEVEL_FATAL);
+ return false;
+ }
+ return true;
+}
+#endif
+
+
+bool Socket::SoAcceptconn()
+{
+ int value = 0;
+#ifdef SO_ACCEPTCONN
+ socklen_t len = sizeof(value);
+ if (getsockopt(GetSocket(), SOL_SOCKET, SO_ACCEPTCONN, (char *)&value, &len) == -1)
+ {
+ Handler().LogError(this, "setsockopt(SOL_SOCKET, SO_ACCEPTCONN)", Errno, StrError(Errno), LOG_LEVEL_FATAL);
+ }
+#else
+ Handler().LogError(this, "socket option not available", 0, "SO_ACCEPTCONN", LOG_LEVEL_INFO);
+#endif
+ return value ? true : false;
+}
+
+
+#ifdef SO_BSDCOMPAT
+bool Socket::SetSoBsdcompat(bool x)
+{
+ int optval = x ? 1 : 0;
+ if (setsockopt(GetSocket(), SOL_SOCKET, SO_BSDCOMPAT, (char *)&optval, sizeof(optval)) == -1)
+ {
+ Handler().LogError(this, "setsockopt(SOL_SOCKET, SO_BSDCOMPAT)", Errno, StrError(Errno), LOG_LEVEL_FATAL);
+ return false;
+ }
+ return true;
+}
+#endif
+
+
+#ifdef SO_BINDTODEVICE
+bool Socket::SetSoBindtodevice(const std::string& intf)
+{
+ if (setsockopt(GetSocket(), SOL_SOCKET, SO_BINDTODEVICE, (char *)intf.c_str(), intf.size()) == -1)
+ {
+ Handler().LogError(this, "setsockopt(SOL_SOCKET, SO_BINDTODEVICE)", Errno, StrError(Errno), LOG_LEVEL_FATAL);
+ return false;
+ }
+ return true;
+}
+#endif
+
+
+bool Socket::SetSoBroadcast(bool x)
+{
+#ifdef SO_BROADCAST
+ int optval = x ? 1 : 0;
+ if (setsockopt(GetSocket(), SOL_SOCKET, SO_BROADCAST, (char *)&optval, sizeof(optval)) == -1)
+ {
+ Handler().LogError(this, "setsockopt(SOL_SOCKET, SO_BROADCAST)", Errno, StrError(Errno), LOG_LEVEL_FATAL);
+ return false;
+ }
+ return true;
+#else
+ Handler().LogError(this, "socket option not available", 0, "SO_BROADCAST", LOG_LEVEL_INFO);
+ return false;
+#endif
+}
+
+
+bool Socket::SetSoDebug(bool x)
+{
+#ifdef SO_DEBUG
+ int optval = x ? 1 : 0;
+ if (setsockopt(GetSocket(), SOL_SOCKET, SO_DEBUG, (char *)&optval, sizeof(optval)) == -1)
+ {
+ Handler().LogError(this, "setsockopt(SOL_SOCKET, SO_DEBUG)", Errno, StrError(Errno), LOG_LEVEL_FATAL);
+ return false;
+ }
+ return true;
+#else
+ Handler().LogError(this, "socket option not available", 0, "SO_DEBUG", LOG_LEVEL_INFO);
+ return false;
+#endif
+}
+
+
+int Socket::SoError()
+{
+ int value = 0;
+#ifdef SO_ERROR
+ socklen_t len = sizeof(value);
+ if (getsockopt(GetSocket(), SOL_SOCKET, SO_ERROR, (char *)&value, &len) == -1)
+ {
+ Handler().LogError(this, "setsockopt(SOL_SOCKET, SO_ERROR)", Errno, StrError(Errno), LOG_LEVEL_FATAL);
+ }
+#else
+ Handler().LogError(this, "socket option not available", 0, "SO_ERROR", LOG_LEVEL_INFO);
+#endif
+ return value ? true : false;
+}
+
+
+bool Socket::SetSoDontroute(bool x)
+{
+#ifdef SO_DONTROUTE
+ int optval = x ? 1 : 0;
+ if (setsockopt(GetSocket(), SOL_SOCKET, SO_DONTROUTE, (char *)&optval, sizeof(optval)) == -1)
+ {
+ Handler().LogError(this, "setsockopt(SOL_SOCKET, SO_DONTROUTE)", Errno, StrError(Errno), LOG_LEVEL_FATAL);
+ return false;
+ }
+ return true;
+#else
+ Handler().LogError(this, "socket option not available", 0, "SO_DONTROUTE", LOG_LEVEL_INFO);
+ return false;
+#endif
+}
+
+
+bool Socket::SetSoLinger(int onoff, int linger)
+{
+#ifdef SO_LINGER
+ struct linger stl;
+ stl.l_onoff = onoff;
+ stl.l_linger = linger;
+ if (setsockopt(GetSocket(), SOL_SOCKET, SO_LINGER, (char *)&stl, sizeof(stl)) == -1)
+ {
+ Handler().LogError(this, "setsockopt(SOL_SOCKET, SO_LINGER)", Errno, StrError(Errno), LOG_LEVEL_FATAL);
+ return false;
+ }
+ return true;
+#else
+ Handler().LogError(this, "socket option not available", 0, "SO_LINGER", LOG_LEVEL_INFO);
+ return false;
+#endif
+}
+
+
+bool Socket::SetSoOobinline(bool x)
+{
+#ifdef SO_OOBINLINE
+ int optval = x ? 1 : 0;
+ if (setsockopt(GetSocket(), SOL_SOCKET, SO_OOBINLINE, (char *)&optval, sizeof(optval)) == -1)
+ {
+ Handler().LogError(this, "setsockopt(SOL_SOCKET, SO_OOBINLINE)", Errno, StrError(Errno), LOG_LEVEL_FATAL);
+ return false;
+ }
+ return true;
+#else
+ Handler().LogError(this, "socket option not available", 0, "SO_OOBINLINE", LOG_LEVEL_INFO);
+ return false;
+#endif
+}
+
+
+#ifdef SO_PASSCRED
+bool Socket::SetSoPasscred(bool x)
+{
+ int optval = x ? 1 : 0;
+ if (setsockopt(GetSocket(), SOL_SOCKET, SO_PASSCRED, (char *)&optval, sizeof(optval)) == -1)
+ {
+ Handler().LogError(this, "setsockopt(SOL_SOCKET, SO_PASSCRED)", Errno, StrError(Errno), LOG_LEVEL_FATAL);
+ return false;
+ }
+ return true;
+}
+#endif
+
+
+#ifdef SO_PEERCRED
+bool Socket::SoPeercred(struct ucred& ucr)
+{
+ if (setsockopt(GetSocket(), SOL_SOCKET, SO_PEERCRED, (char *)&ucr, sizeof(ucr)) == -1)
+ {
+ Handler().LogError(this, "setsockopt(SOL_SOCKET, SO_PEERCRED)", Errno, StrError(Errno), LOG_LEVEL_FATAL);
+ return false;
+ }
+ return true;
+}
+#endif
+
+
+#ifdef SO_PRIORITY
+bool Socket::SetSoPriority(int x)
+{
+ if (setsockopt(GetSocket(), SOL_SOCKET, SO_PRIORITY, (char *)&x, sizeof(x)) == -1)
+ {
+ Handler().LogError(this, "setsockopt(SOL_SOCKET, SO_PRIORITY)", Errno, StrError(Errno), LOG_LEVEL_FATAL);
+ return false;
+ }
+ return true;
+}
+#endif
+
+
+bool Socket::SetSoRcvlowat(int x)
+{
+#ifdef SO_RCVLOWAT
+ if (setsockopt(GetSocket(), SOL_SOCKET, SO_RCVLOWAT, (char *)&x, sizeof(x)) == -1)
+ {
+ Handler().LogError(this, "setsockopt(SOL_SOCKET, SO_RCVLOWAT)", Errno, StrError(Errno), LOG_LEVEL_FATAL);
+ return false;
+ }
+ return true;
+#else
+ Handler().LogError(this, "socket option not available", 0, "SO_RCVLOWAT", LOG_LEVEL_INFO);
+ return false;
+#endif
+}
+
+
+bool Socket::SetSoSndlowat(int x)
+{
+#ifdef SO_SNDLOWAT
+ if (setsockopt(GetSocket(), SOL_SOCKET, SO_SNDLOWAT, (char *)&x, sizeof(x)) == -1)
+ {
+ Handler().LogError(this, "setsockopt(SOL_SOCKET, SO_SNDLOWAT)", Errno, StrError(Errno), LOG_LEVEL_FATAL);
+ return false;
+ }
+ return true;
+#else
+ Handler().LogError(this, "socket option not available", 0, "SO_SNDLOWAT", LOG_LEVEL_INFO);
+ return false;
+#endif
+}
+
+
+bool Socket::SetSoRcvtimeo(struct timeval& tv)
+{
+#ifdef SO_RCVTIMEO
+ if (setsockopt(GetSocket(), SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(tv)) == -1)
+ {
+ Handler().LogError(this, "setsockopt(SOL_SOCKET, SO_RCVTIMEO)", Errno, StrError(Errno), LOG_LEVEL_FATAL);
+ return false;
+ }
+ return true;
+#else
+ Handler().LogError(this, "socket option not available", 0, "SO_RCVTIMEO", LOG_LEVEL_INFO);
+ return false;
+#endif
+}
+
+
+bool Socket::SetSoSndtimeo(struct timeval& tv)
+{
+#ifdef SO_SNDTIMEO
+ if (setsockopt(GetSocket(), SOL_SOCKET, SO_SNDTIMEO, (char *)&tv, sizeof(tv)) == -1)
+ {
+ Handler().LogError(this, "setsockopt(SOL_SOCKET, SO_SNDTIMEO)", Errno, StrError(Errno), LOG_LEVEL_FATAL);
+ return false;
+ }
+ return true;
+#else
+ Handler().LogError(this, "socket option not available", 0, "SO_SNDTIMEO", LOG_LEVEL_INFO);
+ return false;
+#endif
+}
+
+
+bool Socket::SetSoRcvbuf(int x)
+{
+#ifdef SO_RCVBUF
+ if (setsockopt(GetSocket(), SOL_SOCKET, SO_RCVBUF, (char *)&x, sizeof(x)) == -1)
+ {
+ Handler().LogError(this, "setsockopt(SOL_SOCKET, SO_RCVBUF)", Errno, StrError(Errno), LOG_LEVEL_FATAL);
+ return false;
+ }
+ return true;
+#else
+ Handler().LogError(this, "socket option not available", 0, "SO_RCVBUF", LOG_LEVEL_INFO);
+ return false;
+#endif
+}
+
+
+int Socket::SoRcvbuf()
+{
+ int value = 0;
+#ifdef SO_RCVBUF
+ socklen_t len = sizeof(value);
+ if (getsockopt(GetSocket(), SOL_SOCKET, SO_RCVBUF, (char *)&value, &len) == -1)
+ {
+ Handler().LogError(this, "setsockopt(SOL_SOCKET, SO_RCVBUF)", Errno, StrError(Errno), LOG_LEVEL_FATAL);
+ }
+#else
+ Handler().LogError(this, "socket option not available", 0, "SO_RCVBUF", LOG_LEVEL_INFO);
+#endif
+ return value ? true : false;
+}
+
+
+#ifdef SO_RCVBUFFORCE
+bool Socket::SetSoRcvbufforce(int x)
+{
+ if (setsockopt(GetSocket(), SOL_SOCKET, SO_RCVBUFFORCE, (char *)&x, sizeof(x)) == -1)
+ {
+ Handler().LogError(this, "setsockopt(SOL_SOCKET, SO_RCVBUFFORCE)", Errno, StrError(Errno), LOG_LEVEL_FATAL);
+ return false;
+ }
+ return true;
+}
+#endif
+
+
+bool Socket::SetSoSndbuf(int x)
+{
+#ifdef SO_SNDBUF
+ if (setsockopt(GetSocket(), SOL_SOCKET, SO_SNDBUF, (char *)&x, sizeof(x)) == -1)
+ {
+ Handler().LogError(this, "setsockopt(SOL_SOCKET, SO_SNDBUF)", Errno, StrError(Errno), LOG_LEVEL_FATAL);
+ return false;
+ }
+ return true;
+#else
+ Handler().LogError(this, "socket option not available", 0, "SO_SNDBUF", LOG_LEVEL_INFO);
+ return false;
+#endif
+}
+
+
+int Socket::SoSndbuf()
+{
+ int value = 0;
+#ifdef SO_SNDBUF
+ socklen_t len = sizeof(value);
+ if (getsockopt(GetSocket(), SOL_SOCKET, SO_SNDBUF, (char *)&value, &len) == -1)
+ {
+ Handler().LogError(this, "setsockopt(SOL_SOCKET, SO_SNDBUF)", Errno, StrError(Errno), LOG_LEVEL_FATAL);
+ }
+#else
+ Handler().LogError(this, "socket option not available", 0, "SO_SNDBUF", LOG_LEVEL_INFO);
+#endif
+ return value ? true : false;
+}
+
+
+#ifdef SO_SNDBUFFORCE
+bool Socket::SetSoSndbufforce(int x)
+{
+ if (setsockopt(GetSocket(), SOL_SOCKET, SO_SNDBUFFORCE, (char *)&x, sizeof(x)) == -1)
+ {
+ Handler().LogError(this, "setsockopt(SOL_SOCKET, SO_SNDBUFFORCE)", Errno, StrError(Errno), LOG_LEVEL_FATAL);
+ return false;
+ }
+ return true;
+}
+#endif
+
+
+#ifdef SO_TIMESTAMP
+bool Socket::SetSoTimestamp(bool x)
+{
+ int optval = x ? 1 : 0;
+ if (setsockopt(GetSocket(), SOL_SOCKET, SO_TIMESTAMP, (char *)&optval, sizeof(optval)) == -1)
+ {
+ Handler().LogError(this, "setsockopt(SOL_SOCKET, SO_TIMESTAMP)", Errno, StrError(Errno), LOG_LEVEL_FATAL);
+ return false;
+ }
+ return true;
+}
+#endif
+
+
+int Socket::SoType()
+{
+ int value = 0;
+#ifdef SO_TYPE
+ socklen_t len = sizeof(value);
+ if (getsockopt(GetSocket(), SOL_SOCKET, SO_TYPE, (char *)&value, &len) == -1)
+ {
+ Handler().LogError(this, "setsockopt(SOL_SOCKET, SO_TYPE)", Errno, StrError(Errno), LOG_LEVEL_FATAL);
+ }
+#else
+ Handler().LogError(this, "socket option not available", 0, "SO_TYPE", LOG_LEVEL_INFO);
+#endif
+ return value ? true : false;
+}
+
+
+#ifdef ENABLE_TRIGGERS
+void Socket::Subscribe(int id)
+{
+ Handler().Subscribe(id, this);
+}
+
+
+void Socket::Unsubscribe(int id)
+{
+ Handler().Unsubscribe(id, this);
+}
+
+
+void Socket::OnTrigger(int, const TriggerData&)
+{
+}
+
+
+void Socket::OnCancelled(int)
+{
+}
+#endif
+
+
+void Socket::SetTimeout(time_t secs)
+{
+ if (!secs)
+ {
+ Handler().AddList(m_socket, LIST_TIMEOUT, false);
+ return;
+ }
+ Handler().AddList(m_socket, LIST_TIMEOUT, true);
+ m_timeout_start = time(NULL);
+ m_timeout_limit = secs;
+}
+
+
+void Socket::OnTimeout()
+{
+}
+
+
+void Socket::OnConnectTimeout()
+{
+}
+
+
+bool Socket::Timeout(time_t tnow)
+{
+ if (tnow - m_timeout_start > m_timeout_limit)
+ return true;
+ return false;
+}
+
+
+/** Returns local port number for bound socket file descriptor. */
+port_t Socket::GetSockPort()
+{
+#ifdef ENABLE_IPV6
+#ifdef IPPROTO_IPV6
+ if (IsIpv6())
+ {
+ struct sockaddr_in6 sa;
+ socklen_t sockaddr_length = sizeof(struct sockaddr_in6);
+ if (getsockname(GetSocket(), (struct sockaddr *)&sa, (socklen_t*)&sockaddr_length) == -1)
+ memset(&sa, 0, sizeof(sa));
+ return ntohs(sa.sin6_port);
+ }
+#endif
+#endif
+ struct sockaddr_in sa;
+ socklen_t sockaddr_length = sizeof(struct sockaddr_in);
+ if (getsockname(GetSocket(), (struct sockaddr *)&sa, (socklen_t*)&sockaddr_length) == -1)
+ memset(&sa, 0, sizeof(sa));
+ return ntohs(sa.sin_port);
+}
+
+
+/** Returns local ipv4 address for bound socket file descriptor. */
+ipaddr_t Socket::GetSockIP4()
+{
+#ifdef ENABLE_IPV6
+#ifdef IPPROTO_IPV6
+ if (IsIpv6())
+ {
+ return 0;
+ }
+#endif
+#endif
+ struct sockaddr_in sa;
+ socklen_t sockaddr_length = sizeof(struct sockaddr_in);
+ if (getsockname(GetSocket(), (struct sockaddr *)&sa, (socklen_t*)&sockaddr_length) == -1)
+ memset(&sa, 0, sizeof(sa));
+ ipaddr_t a;
+ memcpy(&a, &sa.sin_addr, 4);
+ return a;
+}
+
+
+/** Returns local ipv4 address as text for bound socket file descriptor. */
+std::string Socket::GetSockAddress()
+{
+#ifdef ENABLE_IPV6
+#ifdef IPPROTO_IPV6
+ if (IsIpv6())
+ {
+ return "";
+ }
+#endif
+#endif
+ struct sockaddr_in sa;
+ socklen_t sockaddr_length = sizeof(struct sockaddr_in);
+ if (getsockname(GetSocket(), (struct sockaddr *)&sa, (socklen_t*)&sockaddr_length) == -1)
+ memset(&sa, 0, sizeof(sa));
+ Ipv4Address addr( sa );
+ return addr.Convert();
+}
+
+
+#ifdef ENABLE_IPV6
+#ifdef IPPROTO_IPV6
+/** Returns local ipv6 address for bound socket file descriptor. */
+struct in6_addr Socket::GetSockIP6()
+{
+ if (IsIpv6())
+ {
+ struct sockaddr_in6 sa;
+ socklen_t sockaddr_length = sizeof(struct sockaddr_in6);
+ if (getsockname(GetSocket(), (struct sockaddr *)&sa, (socklen_t*)&sockaddr_length) == -1)
+ memset(&sa, 0, sizeof(sa));
+ return sa.sin6_addr;
+ }
+ struct in6_addr a;
+ memset(&a, 0, sizeof(a));
+ return a;
+}
+
+
+/** Returns local ipv6 address as text for bound socket file descriptor. */
+std::string Socket::GetSockAddress6()
+{
+ if (IsIpv6())
+ {
+ struct sockaddr_in6 sa;
+ socklen_t sockaddr_length = sizeof(struct sockaddr_in6);
+ if (getsockname(GetSocket(), (struct sockaddr *)&sa, (socklen_t*)&sockaddr_length) == -1)
+ memset(&sa, 0, sizeof(sa));
+ Ipv6Address addr( sa );
+ return addr.Convert();
+ }
+ return "";
+}
+#endif
+#endif
+
+
+#ifdef SOCKETS_NAMESPACE
+}
+#endif
+
diff --git a/Sockets/Socket.h b/Sockets/Socket.h
new file mode 100644
index 0000000..764b69b
--- /dev/null
+++ b/Sockets/Socket.h
@@ -0,0 +1,738 @@
+/** \file Socket.h
+ ** \date 2004-02-13
+ ** \author grymse@alhem.net
+**/
+/*
+Copyright (C) 2004-2007 Anders Hedstrom
+
+This software is made available under the terms of the GNU GPL.
+
+If you would like to use this library in a closed-source application,
+a separate license agreement is available. For information about
+the closed-source license agreement for the C++ sockets library,
+please visit http://www.alhem.net/Sockets/license.html and/or
+email license@alhem.net.
+
+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.
+*/
+#ifndef _SOCKETS_Socket_H
+#define _SOCKETS_Socket_H
+#include "sockets-config.h"
+
+#include <string>
+#include <vector>
+#include <list>
+#ifdef HAVE_OPENSSL
+#include <openssl/ssl.h>
+#endif
+
+#include "socket_include.h"
+#include <time.h>
+#include "SocketAddress.h"
+#include "Thread.h"
+
+
+#ifdef SOCKETS_NAMESPACE
+namespace SOCKETS_NAMESPACE {
+#endif
+
+
+class ISocketHandler;
+class SocketAddress;
+class IFile;
+
+
+/** \defgroup basic Basic sockets */
+/** Socket base class.
+ \ingroup basic */
+class Socket
+{
+ friend class ISocketHandler;
+#ifdef ENABLE_DETACH
+ /** Detached socket run thread.
+ \ingroup internal */
+ class SocketThread : public Thread
+ {
+ public:
+ SocketThread(Socket *p);
+ ~SocketThread();
+
+ void Run();
+
+ private:
+ Socket *GetSocket() const { return m_socket; }
+ SocketThread(const SocketThread& s) : m_socket(s.GetSocket()) {}
+ SocketThread& operator=(const SocketThread& ) { return *this; }
+ Socket *m_socket;
+ };
+#endif // ENABLE_DETACH
+
+#ifdef ENABLE_TRIGGERS
+public:
+ /** Data pass class from source to destination. */
+ class TriggerData
+ {
+ public:
+ TriggerData() : m_src(NULL) {}
+ virtual ~TriggerData() {}
+
+ Socket *GetSource() const { return m_src; }
+ void SetSource(Socket *x) { m_src = x; }
+
+ private:
+ Socket *m_src;
+ };
+#endif // ENABLE_TRIGGERS
+
+ /** Socket mode flags. */
+/*
+ enum {
+ // Socket
+ SOCK_DEL = 0x01, ///< Delete by handler flag
+ SOCK_CLOSE = 0x02, ///< Close and delete flag
+ SOCK_DISABLE_READ = 0x04, ///< Disable checking for read events
+ SOCK_CONNECTED = 0x08, ///< Socket is connected (tcp/udp)
+
+ SOCK_ERASED_BY_HANDLER = 0x10, ///< Set by handler before delete
+ // HAVE_OPENSSL
+ SOCK_ENABLE_SSL = 0x20, ///< Enable SSL for this TcpSocket
+ SOCK_SSL = 0x40, ///< ssl negotiation mode (TcpSocket)
+ SOCK_SSL_SERVER = 0x80, ///< True if this is an incoming ssl TcpSocket connection
+
+ // ENABLE_IPV6
+ SOCK_IPV6 = 0x0100, ///< This is an ipv6 socket if this one is true
+ // ENABLE_POOL
+ SOCK_CLIENT = 0x0200, ///< only client connections are pooled
+ SOCK_RETAIN = 0x0400, ///< keep connection on close
+ SOCK_LOST = 0x0800, ///< connection lost
+
+ // ENABLE_SOCKS4
+ SOCK_SOCKS4 = 0x1000, ///< socks4 negotiation mode (TcpSocket)
+ // ENABLE_DETACH
+ SOCK_DETACH = 0x2000, ///< Socket ordered to detach flag
+ SOCK_DETACHED = 0x4000, ///< Socket has been detached
+ // StreamSocket
+ STREAMSOCK_CONNECTING = 0x8000, ///< Flag indicating connection in progress
+
+ STREAMSOCK_FLUSH_BEFORE_CLOSE = 0x010000L, ///< Send all data before closing (default true)
+ STREAMSOCK_CALL_ON_CONNECT = 0x020000L, ///< OnConnect will be called next ISocketHandler cycle if true
+ STREAMSOCK_RETRY_CONNECT = 0x040000L, ///< Try another connection attempt next ISocketHandler cycle
+ STREAMSOCK_LINE_PROTOCOL = 0x080000L, ///< Line protocol mode flag
+
+ };
+*/
+
+public:
+ /** "Default" constructor */
+ Socket(ISocketHandler&);
+
+ virtual ~Socket();
+
+ /** Socket class instantiation method. Used when a "non-standard" constructor
+ * needs to be used for the socket class. Note: the socket class still needs
+ * the "default" constructor with one ISocketHandler& as input parameter.
+ */
+ virtual Socket *Create() { return NULL; }
+
+ /** Returns reference to sockethandler that owns the socket.
+ If the socket is detached, this is a reference to the slave sockethandler.
+ */
+ ISocketHandler& Handler() const;
+
+ /** Returns reference to sockethandler that owns the socket.
+ This one always returns the reference to the original sockethandler,
+ even if the socket is detached.
+ */
+ ISocketHandler& MasterHandler() const;
+
+ /** Called by ListenSocket after accept but before socket is added to handler.
+ * CTcpSocket uses this to create its ICrypt member variable.
+ * The ICrypt member variable is created by a virtual method, therefore
+ * it can't be called directly from the CTcpSocket constructor.
+ * Also used to determine if incoming HTTP connection is normal (port 80)
+ * or ssl (port 443).
+ */
+ virtual void Init();
+
+ /** Create a socket file descriptor.
+ \param af Address family AF_INET / AF_INET6 / ...
+ \param type SOCK_STREAM / SOCK_DGRAM / ...
+ \param protocol "tcp" / "udp" / ... */
+ SOCKET CreateSocket(int af,int type,const std::string& protocol = "");
+
+ /** Assign this socket a file descriptor created
+ by a call to socket() or otherwise. */
+ void Attach(SOCKET s);
+
+ /** Return file descriptor assigned to this socket. */
+ SOCKET GetSocket();
+
+ /** Close connection immediately - internal use.
+ \sa SetCloseAndDelete */
+ virtual int Close();
+
+ /** Add file descriptor to sockethandler fd_set's. */
+ void Set(bool bRead,bool bWrite,bool bException = true);
+
+ /** Returns true when socket file descriptor is valid
+ and socket is not about to be closed. */
+ virtual bool Ready();
+
+ /** Returns pointer to ListenSocket that created this instance
+ * on an incoming connection. */
+ Socket *GetParent();
+
+ /** Used by ListenSocket to set parent pointer of newly created
+ * socket instance. */
+ void SetParent(Socket *);
+
+ /** Get listening port from ListenSocket<>. */
+ virtual port_t GetPort();
+
+ /** Set socket non-block operation. */
+ bool SetNonblocking(bool);
+
+ /** Set socket non-block operation. */
+ bool SetNonblocking(bool, SOCKET);
+
+ /** Total lifetime of instance. */
+ time_t Uptime();
+
+ /** Set address/port of last connect() call. */
+ void SetClientRemoteAddress(SocketAddress&);
+
+ /** Get address/port of last connect() call. */
+ std::auto_ptr<SocketAddress> GetClientRemoteAddress();
+
+ /** Common interface for SendBuf used by Tcp and Udp sockets. */
+ virtual void SendBuf(const char *,size_t,int = 0);
+
+ /** Common interface for Send used by Tcp and Udp sockets. */
+ virtual void Send(const std::string&,int = 0);
+
+ /** Outgoing traffic counter. */
+ virtual uint64_t GetBytesSent(bool clear = false);
+
+ /** Incoming traffic counter. */
+ virtual uint64_t GetBytesReceived(bool clear = false);
+
+ // LIST_TIMEOUT
+
+ /** Enable timeout control. 0=disable timeout check. */
+ void SetTimeout(time_t secs);
+
+ /** Check timeout. \return true if time limit reached */
+ bool Timeout(time_t tnow);
+
+ /** Used by ListenSocket. ipv4 and ipv6 */
+ void SetRemoteAddress(SocketAddress&);
+
+ /** \name Event callbacks */
+ //@{
+
+ /** Called when there is something to be read from the file descriptor. */
+ virtual void OnRead();
+ /** Called when there is room for another write on the file descriptor. */
+ virtual void OnWrite();
+ /** Called on socket exception. */
+ virtual void OnException();
+ /** Called before a socket class is deleted by the ISocketHandler. */
+ virtual void OnDelete();
+ /** Called when a connection has completed. */
+ virtual void OnConnect();
+ /** Called when an incoming connection has been completed. */
+ virtual void OnAccept();
+ /** Called when a complete line has been read and the socket is in
+ * line protocol mode. */
+ virtual void OnLine(const std::string& );
+ /** Called on connect timeout (5s). */
+ virtual void OnConnectFailed();
+ /** Called when a client socket is created, to set socket options.
+ \param family AF_INET, AF_INET6, etc
+ \param type SOCK_STREAM, SOCK_DGRAM, etc
+ \param protocol Protocol number (tcp, udp, sctp, etc)
+ \param s Socket file descriptor
+ */
+ virtual void OnOptions(int family,int type,int protocol,SOCKET s) = 0;
+ /** Connection retry callback - return false to abort connection attempts */
+ virtual bool OnConnectRetry();
+#ifdef ENABLE_RECONNECT
+ /** a reconnect has been made */
+ virtual void OnReconnect();
+#endif
+ /** TcpSocket: When a disconnect has been detected (recv/SSL_read returns 0 bytes). */
+ virtual void OnDisconnect();
+ /** Timeout callback. */
+ virtual void OnTimeout();
+ /** Connection timeout. */
+ virtual void OnConnectTimeout();
+ //@}
+
+ /** \name Socket mode flags, set/reset */
+ //@{
+ /** Set delete by handler true when you want the sockethandler to
+ delete the socket instance after use. */
+ void SetDeleteByHandler(bool = true);
+ /** Check delete by handler flag.
+ \return true if this instance should be deleted by the sockethandler */
+ bool DeleteByHandler();
+
+ // LIST_CLOSE - conditional event queue
+
+ /** Set close and delete to terminate the connection. */
+ void SetCloseAndDelete(bool = true);
+ /** Check close and delete flag.
+ \return true if this socket should be closed and the instance removed */
+ bool CloseAndDelete();
+
+ /** Return number of seconds since socket was ordered to close. \sa SetCloseAndDelete */
+ time_t TimeSinceClose();
+
+ /** Ignore read events for an output only socket. */
+ void DisableRead(bool x = true);
+ /** Check ignore read events flag.
+ \return true if read events should be ignored */
+ bool IsDisableRead();
+
+ /** Set connected status. */
+ void SetConnected(bool = true);
+ /** Check connected status.
+ \return true if connected */
+ bool IsConnected();
+
+ /** Set flag indicating the socket is being actively deleted by the sockethandler. */
+ void SetErasedByHandler(bool x = true);
+ /** Get value of flag indicating socket is deleted by sockethandler. */
+ bool ErasedByHandler();
+
+ //@}
+
+ /** \name Information about remote connection */
+ //@{
+ /** Returns address of remote end. */
+ std::auto_ptr<SocketAddress> GetRemoteSocketAddress();
+ /** Returns address of remote end: ipv4. */
+ ipaddr_t GetRemoteIP4();
+#ifdef ENABLE_IPV6
+ /** Returns address of remote end: ipv6. */
+#ifdef IPPROTO_IPV6
+ struct in6_addr GetRemoteIP6();
+#endif
+#endif
+ /** Returns remote port number: ipv4 and ipv6. */
+ port_t GetRemotePort();
+ /** Returns remote ip as string? ipv4 and ipv6. */
+ std::string GetRemoteAddress();
+ /** ipv4 and ipv6(not implemented) */
+ std::string GetRemoteHostname();
+ //@}
+
+ /** Returns local port number for bound socket file descriptor. */
+ port_t GetSockPort();
+ /** Returns local ipv4 address for bound socket file descriptor. */
+ ipaddr_t GetSockIP4();
+ /** Returns local ipv4 address as text for bound socket file descriptor. */
+ std::string GetSockAddress();
+#ifdef ENABLE_IPV6
+#ifdef IPPROTO_IPV6
+ /** Returns local ipv6 address for bound socket file descriptor. */
+ struct in6_addr GetSockIP6();
+ /** Returns local ipv6 address as text for bound socket file descriptor. */
+ std::string GetSockAddress6();
+#endif
+#endif
+ // --------------------------------------------------------------------------
+ /** @name IP options
+ When an ip or socket option is available on all of the operating systems
+ I'm testing on (linux 2.4.x, _win32, macosx, solaris9 intel) they are not
+ checked with an #ifdef below.
+ This might cause a compile error on other operating systems. */
+ // --------------------------------------------------------------------------
+
+ // IP options
+ //@{
+
+ bool SetIpOptions(const void *p, socklen_t len);
+ bool SetIpTOS(unsigned char tos);
+ unsigned char IpTOS();
+ bool SetIpTTL(int ttl);
+ int IpTTL();
+ bool SetIpHdrincl(bool x = true);
+ bool SetIpMulticastTTL(int);
+ int IpMulticastTTL();
+ bool SetMulticastLoop(bool x = true);
+ bool IpAddMembership(struct ip_mreq&);
+ bool IpDropMembership(struct ip_mreq&);
+
+#ifdef IP_PKTINFO
+ bool SetIpPktinfo(bool x = true);
+#endif
+#ifdef IP_RECVTOS
+ bool SetIpRecvTOS(bool x = true);
+#endif
+#ifdef IP_RECVTTL
+ bool SetIpRecvTTL(bool x = true);
+#endif
+#ifdef IP_RECVOPTS
+ bool SetIpRecvopts(bool x = true);
+#endif
+#ifdef IP_RETOPTS
+ bool SetIpRetopts(bool x = true);
+#endif
+#ifdef IP_RECVERR
+ bool SetIpRecverr(bool x = true);
+#endif
+#ifdef IP_MTU_DISCOVER
+ bool SetIpMtudiscover(bool x = true);
+#endif
+#ifdef IP_MTU
+ int IpMtu();
+#endif
+#ifdef IP_ROUTER_ALERT
+ bool SetIpRouterAlert(bool x = true);
+#endif
+#ifdef LINUX
+ bool IpAddMembership(struct ip_mreqn&);
+#endif
+#ifdef LINUX
+ bool IpDropMembership(struct ip_mreqn&);
+#endif
+ //@}
+
+ // SOCKET options
+ /** @name Socket Options */
+ //@{
+
+ bool SoAcceptconn();
+ bool SetSoBroadcast(bool x = true);
+ bool SetSoDebug(bool x = true);
+ int SoError();
+ bool SetSoDontroute(bool x = true);
+ bool SetSoLinger(int onoff, int linger);
+ bool SetSoOobinline(bool x = true);
+ bool SetSoRcvlowat(int);
+ bool SetSoSndlowat(int);
+ bool SetSoRcvtimeo(struct timeval&);
+ bool SetSoSndtimeo(struct timeval&);
+ bool SetSoRcvbuf(int);
+ int SoRcvbuf();
+ bool SetSoSndbuf(int);
+ int SoSndbuf();
+ int SoType();
+ bool SetSoReuseaddr(bool x = true);
+ bool SetSoKeepalive(bool x = true);
+
+#ifdef SO_BSDCOMPAT
+ bool SetSoBsdcompat(bool x = true);
+#endif
+#ifdef SO_BINDTODEVICE
+ bool SetSoBindtodevice(const std::string& intf);
+#endif
+#ifdef SO_PASSCRED
+ bool SetSoPasscred(bool x = true);
+#endif
+#ifdef SO_PEERCRED
+ bool SoPeercred(struct ucred& );
+#endif
+#ifdef SO_PRIORITY
+ bool SetSoPriority(int);
+#endif
+#ifdef SO_RCVBUFFORCE
+ bool SetSoRcvbufforce(int);
+#endif
+#ifdef SO_SNDBUFFORCE
+ bool SetSoSndbufforce(int);
+#endif
+#ifdef SO_TIMESTAMP
+ bool SetSoTimestamp(bool x = true);
+#endif
+#ifdef SO_NOSIGPIPE
+ bool SetSoNosigpipe(bool x = true);
+#endif
+ //@}
+
+ // TCP options in TcpSocket.h/TcpSocket.cpp
+
+
+#ifdef HAVE_OPENSSL
+ /** @name SSL Support */
+ //@{
+ /** SSL client/server support - internal use. \sa TcpSocket */
+ virtual void OnSSLConnect();
+ /** SSL client/server support - internal use. \sa TcpSocket */
+ virtual void OnSSLAccept();
+ /** SSL negotiation failed for client connect. */
+ virtual void OnSSLConnectFailed();
+ /** SSL negotiation failed for server accept. */
+ virtual void OnSSLAcceptFailed();
+ /** new SSL support */
+ virtual bool SSLNegotiate();
+ /** Check if SSL is Enabled for this TcpSocket.
+ \return true if this is a TcpSocket with SSL enabled */
+ bool IsSSL();
+ /** Enable SSL operation for a TcpSocket. */
+ void EnableSSL(bool x = true);
+ /** Still negotiating ssl connection.
+ \return true if ssl negotiating is still in progress */
+ bool IsSSLNegotiate();
+ /** Set flag indicating ssl handshaking still in progress. */
+ void SetSSLNegotiate(bool x = true);
+ /** OnAccept called with SSL Enabled.
+ \return true if this is a TcpSocket with an incoming SSL connection */
+ bool IsSSLServer();
+ /** Set flag indicating that this is a TcpSocket with incoming SSL connection. */
+ void SetSSLServer(bool x = true);
+ /** SSL; Get pointer to ssl context structure. */
+ virtual SSL_CTX *GetSslContext() { return NULL; }
+ /** SSL; Get pointer to ssl structure. */
+ virtual SSL *GetSsl() { return NULL; }
+ //@}
+#endif // HAVE_OPENSSL
+
+#ifdef ENABLE_IPV6
+ /** Enable ipv6 for this socket. */
+ void SetIpv6(bool x = true);
+ /** Check ipv6 socket.
+ \return true if this is an ipv6 socket */
+ bool IsIpv6();
+#endif
+
+#ifdef ENABLE_POOL
+ /** @name Connection Pool */
+ //@{
+ /** Client = connecting TcpSocket. */
+ void SetIsClient();
+ /** Socket type from socket() call. */
+ void SetSocketType(int x);
+ /** Socket type from socket() call. */
+ int GetSocketType();
+ /** Protocol type from socket() call. */
+ void SetSocketProtocol(const std::string& x);
+ /** Protocol type from socket() call. */
+ const std::string& GetSocketProtocol();
+ /** Instruct a client socket to stay open in the connection pool after use.
+ If you have connected to a server using tcp, you can call SetRetain
+ to leave the connection open after your socket instance has been deleted.
+ The next connection you make to the same server will reuse the already
+ opened connection, if it is still available.
+ */
+ void SetRetain();
+ /** Check retain flag.
+ \return true if the socket should be moved to connection pool after use */
+ bool Retain();
+ /** Connection lost - error while reading/writing from a socket - TcpSocket only. */
+ void SetLost();
+ /** Check connection lost status flag, used by TcpSocket only.
+ \return true if there was an error while r/w causing the socket to close */
+ bool Lost();
+ /** Copy connection parameters from sock. */
+ void CopyConnection(Socket *sock);
+ //@}
+#endif // ENABLE_POOL
+
+#ifdef ENABLE_SOCKS4
+ /** \name Socks4 support */
+ //@{
+ /** Socks4 client support internal use. \sa TcpSocket */
+ virtual void OnSocks4Connect();
+ /** Socks4 client support internal use. \sa TcpSocket */
+ virtual void OnSocks4ConnectFailed();
+ /** Socks4 client support internal use. \sa TcpSocket */
+ virtual bool OnSocks4Read();
+ /** Called when the last write caused the tcp output buffer to
+ * become empty. */
+ /** socket still in socks4 negotiation mode */
+ bool Socks4();
+ /** Set flag indicating Socks4 handshaking in progress */
+ void SetSocks4(bool x = true);
+
+ /** Set socks4 server host address to use */
+ void SetSocks4Host(ipaddr_t a);
+ /** Set socks4 server hostname to use. */
+ void SetSocks4Host(const std::string& );
+ /** Socks4 server port to use. */
+ void SetSocks4Port(port_t p);
+ /** Provide a socks4 userid if required by the socks4 server. */
+ void SetSocks4Userid(const std::string& x);
+ /** Get the ip address of socks4 server to use.
+ \return socks4 server host address */
+ ipaddr_t GetSocks4Host();
+ /** Get the socks4 server port to use.
+ \return socks4 server port */
+ port_t GetSocks4Port();
+ /** Get socks4 userid.
+ \return Socks4 userid */
+ const std::string& GetSocks4Userid();
+ //@}
+#endif // ENABLE_SOCKS4
+
+#ifdef ENABLE_RESOLVER
+ /** \name Asynchronous Resolver */
+ //@{
+ /** Request an asynchronous dns resolution.
+ \param host hostname to be resolved
+ \param port port number passed along for the ride
+ \return Resolve ID */
+ int Resolve(const std::string& host,port_t port = 0);
+#ifdef ENABLE_IPV6
+ int Resolve6(const std::string& host, port_t port = 0);
+#endif
+ /** Callback returning a resolved address.
+ \param id Resolve ID from Resolve call
+ \param a resolved ip address
+ \param port port number passed to Resolve */
+ virtual void OnResolved(int id,ipaddr_t a,port_t port);
+#ifdef ENABLE_IPV6
+ virtual void OnResolved(int id,in6_addr& a,port_t port);
+#endif
+ /** Request asynchronous reverse dns lookup.
+ \param a in_addr to be translated */
+ int Resolve(ipaddr_t a);
+#ifdef ENABLE_IPV6
+ int Resolve(in6_addr& a);
+#endif
+ /** Callback returning reverse resolve results.
+ \param id Resolve ID
+ \param name Resolved hostname */
+ virtual void OnReverseResolved(int id,const std::string& name);
+ /** Callback indicating failed dns lookup.
+ \param id Resolve ID */
+ virtual void OnResolveFailed(int id);
+ //@}
+#endif // ENABLE_RESOLVER
+
+#ifdef ENABLE_DETACH
+ /** \name Thread Support */
+ //@{
+ /** Callback fires when a new socket thread has started and this
+ socket is ready for operation again.
+ \sa ResolvSocket */
+ virtual void OnDetached();
+
+ // LIST_DETACH
+
+ /** Internal use. */
+ void SetDetach(bool x = true);
+ /** Check detach flag.
+ \return true if the socket should detach to its own thread */
+ bool IsDetach();
+
+ /** Internal use. */
+ void SetDetached(bool x = true);
+ /** Check detached flag.
+ \return true if the socket runs in its own thread. */
+ const bool IsDetached() const;
+ /** Order this socket to start its own thread and call OnDetached
+ when ready for operation. */
+ bool Detach();
+ /** Store the slave sockethandler pointer. */
+ void SetSlaveHandler(ISocketHandler *);
+ /** Create new thread for this socket to run detached in. */
+ void DetachSocket();
+ //@}
+#endif // ENABLE_DETACH
+
+ /** Write traffic to an IFile. Socket will not delete this object. */
+ void SetTrafficMonitor(IFile *p) { m_traffic_monitor = p; }
+
+#ifdef ENABLE_TRIGGERS
+ /** \name Triggers */
+ //@{
+ /** Subscribe to trigger id. */
+ void Subscribe(int id);
+ /** Unsubscribe from trigger id. */
+ void Unsubscribe(int id);
+ /** Trigger callback, with data passed from source to destination. */
+ virtual void OnTrigger(int id, const TriggerData& data);
+ /** Trigger cancelled because source has been deleted (as in delete). */
+ virtual void OnCancelled(int id);
+ //@}
+#endif
+
+protected:
+ /** default constructor not available */
+ Socket() : m_handler(m_handler) {}
+ /** copy constructor not available */
+ Socket(const Socket& s) : m_handler(s.m_handler) {}
+
+ /** assignment operator not available. */
+ Socket& operator=(const Socket& ) { return *this; }
+
+ /** All traffic will be written to this IFile, if set. */
+ IFile *GetTrafficMonitor() { return m_traffic_monitor; }
+
+// unsigned long m_flags; ///< boolean flags, replacing old 'bool' members
+
+private:
+ ISocketHandler& m_handler; ///< Reference of ISocketHandler in control of this socket
+ SOCKET m_socket; ///< File descriptor
+ bool m_bDel; ///< Delete by handler flag
+ bool m_bClose; ///< Close and delete flag
+ time_t m_tCreate; ///< Time in seconds when this socket was created
+ Socket *m_parent; ///< Pointer to ListenSocket class, valid for incoming sockets
+ bool m_b_disable_read; ///< Disable checking for read events
+ bool m_connected; ///< Socket is connected (tcp/udp)
+ bool m_b_erased_by_handler; ///< Set by handler before delete
+ time_t m_tClose; ///< Time in seconds when ordered to close
+ std::auto_ptr<SocketAddress> m_client_remote_address; ///< Address of last connect()
+ std::auto_ptr<SocketAddress> m_remote_address; ///< Remote end address
+ IFile *m_traffic_monitor;
+ time_t m_timeout_start; ///< Set by SetTimeout
+ time_t m_timeout_limit; ///< Defined by SetTimeout
+
+#ifdef _WIN32
+static WSAInitializer m_winsock_init; ///< Winsock initialization singleton class
+#endif
+
+#ifdef HAVE_OPENSSL
+ bool m_b_enable_ssl; ///< Enable SSL for this TcpSocket
+ bool m_b_ssl; ///< ssl negotiation mode (TcpSocket)
+ bool m_b_ssl_server; ///< True if this is an incoming ssl TcpSocket connection
+#endif
+
+#ifdef ENABLE_IPV6
+ bool m_ipv6; ///< This is an ipv6 socket if this one is true
+#endif
+
+#ifdef ENABLE_POOL
+ int m_socket_type; ///< Type of socket, from socket() call
+ std::string m_socket_protocol; ///< Protocol, from socket() call
+ bool m_bClient; ///< only client connections are pooled
+ bool m_bRetain; ///< keep connection on close
+ bool m_bLost; ///< connection lost
+#endif
+
+#ifdef ENABLE_SOCKS4
+ bool m_bSocks4; ///< socks4 negotiation mode (TcpSocket)
+ ipaddr_t m_socks4_host; ///< socks4 server address
+ port_t m_socks4_port; ///< socks4 server port number
+ std::string m_socks4_userid; ///< socks4 server usedid
+#endif
+
+#ifdef ENABLE_DETACH
+ bool m_detach; ///< Socket ordered to detach flag
+ bool m_detached; ///< Socket has been detached
+ SocketThread *m_pThread; ///< Detach socket thread class pointer
+ ISocketHandler *m_slave_handler; ///< Actual sockethandler while detached
+#endif
+};
+
+#ifdef SOCKETS_NAMESPACE
+}
+#endif
+
+
+#endif // _SOCKETS_Socket_H
+
diff --git a/Sockets/SocketAddress.h b/Sockets/SocketAddress.h
new file mode 100644
index 0000000..d5a5643
--- /dev/null
+++ b/Sockets/SocketAddress.h
@@ -0,0 +1,95 @@
+/**
+ ** \file SocketAddress.h
+ ** \date 2006-09-21
+ ** \author grymse@alhem.net
+**/
+/*
+Copyright (C) 2007 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.
+*/
+#ifndef _SOCKETS_SocketAddress_H
+#define _SOCKETS_SocketAddress_H
+
+#include "sockets-config.h"
+#include <string>
+#include <memory>
+#include "socket_include.h"
+
+#ifdef SOCKETS_NAMESPACE
+namespace SOCKETS_NAMESPACE {
+#endif
+
+
+/**
+ This class and its subclasses is intended to be used as replacement
+ for the internal data type 'ipaddr_t' and various implementations of
+ IPv6 addressing found throughout the library.
+ 'ipaddr_t' is an IPv4 address in network byte order.
+ 'port_t' is the portnumber in host byte order.
+ 'struct in6_addr' is an IPv6 address.
+ 'struct in_addr' is an IPv4 address.
+ \ingroup basic
+*/
+class SocketAddress
+{
+public:
+ virtual ~SocketAddress() {}
+
+ /** Get a pointer to the address struct. */
+ virtual operator struct sockaddr *() = 0;
+
+ /** Get length of address struct. */
+ virtual operator socklen_t() = 0;
+
+ /** Compare two addresses. */
+ virtual bool operator==(SocketAddress&) = 0;
+
+ /** Set port number.
+ \param port Port number in host byte order */
+ virtual void SetPort(port_t port) = 0;
+
+ /** Get port number.
+ \return Port number in host byte order. */
+ virtual port_t GetPort() = 0;
+
+ /** Set socket address.
+ \param sa Pointer to either 'struct sockaddr_in' or 'struct sockaddr_in6'. */
+ virtual void SetAddress(struct sockaddr *sa) = 0;
+
+ /** Convert address to text. */
+ virtual std::string Convert(bool include_port) = 0;
+
+ /** Reverse lookup of address. */
+ virtual std::string Reverse() = 0;
+
+ /** Get address family. */
+ virtual int GetFamily() = 0;
+
+ /** Address structure is valid. */
+ virtual bool IsValid() = 0;
+
+ /** Get a copy of this SocketAddress object. */
+ virtual std::auto_ptr<SocketAddress> GetCopy() = 0;
+};
+
+
+
+
+#ifdef SOCKETS_NAMESPACE
+} // namespace SOCKETS_NAMESPACE {
+#endif
+#endif // _SOCKETS_SocketAddress_H
+
diff --git a/Sockets/SocketHandler.cpp b/Sockets/SocketHandler.cpp
new file mode 100644
index 0000000..c563aac
--- /dev/null
+++ b/Sockets/SocketHandler.cpp
@@ -0,0 +1,1422 @@
+/** \file SocketHandler.cpp
+ ** \date 2004-02-13
+ ** \author grymse@alhem.net
+**/
+/*
+Copyright (C) 2004-2007 Anders Hedstrom
+
+This library is made available under the terms of the GNU GPL.
+
+If you would like to use this library in a closed-source application,
+a separate license agreement is available. For information about
+the closed-source license agreement for the C++ sockets library,
+please visit http://www.alhem.net/Sockets/license.html and/or
+email license@alhem.net.
+
+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
+#ifdef _MSC_VER
+#pragma warning(disable:4786)
+#endif
+#endif
+#include <stdlib.h>
+#include <errno.h>
+
+#include "SocketHandler.h"
+#include "UdpSocket.h"
+#include "ResolvSocket.h"
+#include "ResolvServer.h"
+#include "TcpSocket.h"
+#include "Mutex.h"
+#include "Utility.h"
+#include "SocketAddress.h"
+
+#ifdef SOCKETS_NAMESPACE
+namespace SOCKETS_NAMESPACE {
+#endif
+
+
+#ifdef _DEBUG
+#define DEB(x) x; fflush(stderr);
+#else
+#define DEB(x)
+#endif
+
+
+SocketHandler::SocketHandler(StdLog *p)
+:m_stdlog(p)
+,m_mutex(m_mutex)
+,m_b_use_mutex(false)
+,m_maxsock(0)
+,m_preverror(-1)
+,m_errcnt(0)
+,m_tlast(0)
+#ifdef ENABLE_SOCKS4
+,m_socks4_host(0)
+,m_socks4_port(0)
+,m_bTryDirect(false)
+#endif
+#ifdef ENABLE_RESOLVER
+,m_resolv_id(0)
+,m_resolver(NULL)
+#endif
+#ifdef ENABLE_POOL
+,m_b_enable_pool(false)
+#endif
+#ifdef ENABLE_TRIGGERS
+,m_next_trigger_id(0)
+#endif
+#ifdef ENABLE_DETACH
+,m_slave(false)
+#endif
+{
+ FD_ZERO(&m_rfds);
+ FD_ZERO(&m_wfds);
+ FD_ZERO(&m_efds);
+}
+
+
+SocketHandler::SocketHandler(Mutex& mutex,StdLog *p)
+:m_stdlog(p)
+,m_mutex(mutex)
+,m_b_use_mutex(true)
+,m_maxsock(0)
+,m_preverror(-1)
+,m_errcnt(0)
+,m_tlast(0)
+#ifdef ENABLE_SOCKS4
+,m_socks4_host(0)
+,m_socks4_port(0)
+,m_bTryDirect(false)
+#endif
+#ifdef ENABLE_RESOLVER
+,m_resolv_id(0)
+,m_resolver(NULL)
+#endif
+#ifdef ENABLE_POOL
+,m_b_enable_pool(false)
+#endif
+#ifdef ENABLE_TRIGGERS
+,m_next_trigger_id(0)
+#endif
+#ifdef ENABLE_DETACH
+,m_slave(false)
+#endif
+{
+ m_mutex.Lock();
+ FD_ZERO(&m_rfds);
+ FD_ZERO(&m_wfds);
+ FD_ZERO(&m_efds);
+}
+
+
+SocketHandler::~SocketHandler()
+{
+#ifdef ENABLE_RESOLVER
+ if (m_resolver)
+ {
+ m_resolver -> Quit();
+ }
+#endif
+ {
+ while (m_sockets.size())
+ {
+DEB( fprintf(stderr, "Emptying sockets list in SocketHandler destructor, %d instances\n", (int)m_sockets.size());)
+ socket_m::iterator it = m_sockets.begin();
+ Socket *p = it -> second;
+ if (p)
+ {
+DEB( fprintf(stderr, " fd %d\n", p -> GetSocket());)
+ p -> Close();
+DEB( fprintf(stderr, " fd closed %d\n", p -> GetSocket());)
+// p -> OnDelete(); // hey, I turn this back on. what's the worst that could happen??!!
+ // MinionSocket breaks, calling MinderHandler methods in OnDelete -
+ // MinderHandler is already gone when that happens...
+
+ // only delete socket when controlled
+ // ie master sockethandler can delete non-detached sockets
+ // and a slave sockethandler can only delete a detach socket
+ if (p -> DeleteByHandler()
+#ifdef ENABLE_DETACH
+ && !(m_slave ^ p -> IsDetached())
+#endif
+ )
+ {
+ p -> SetErasedByHandler();
+ delete p;
+ }
+ m_sockets.erase(it);
+ }
+ else
+ {
+ m_sockets.erase(it);
+ }
+DEB( fprintf(stderr, "next\n");)
+ }
+DEB( fprintf(stderr, "/Emptying sockets list in SocketHandler destructor, %d instances\n", (int)m_sockets.size());)
+ }
+#ifdef ENABLE_RESOLVER
+ if (m_resolver)
+ {
+ delete m_resolver;
+ }
+#endif
+ if (m_b_use_mutex)
+ {
+ m_mutex.Unlock();
+ }
+}
+
+
+Mutex& SocketHandler::GetMutex() const
+{
+ return m_mutex;
+}
+
+
+#ifdef ENABLE_DETACH
+void SocketHandler::SetSlave(bool x)
+{
+ m_slave = x;
+}
+
+
+bool SocketHandler::IsSlave()
+{
+ return m_slave;
+}
+#endif
+
+
+void SocketHandler::RegStdLog(StdLog *log)
+{
+ m_stdlog = log;
+}
+
+
+void SocketHandler::LogError(Socket *p,const std::string& user_text,int err,const std::string& sys_err,loglevel_t t)
+{
+ if (m_stdlog)
+ {
+ m_stdlog -> error(this, p, user_text, err, sys_err, t);
+ }
+}
+
+
+void SocketHandler::Add(Socket *p)
+{
+ if (p -> GetSocket() == INVALID_SOCKET)
+ {
+ LogError(p, "Add", -1, "Invalid socket", LOG_LEVEL_WARNING);
+ if (p -> CloseAndDelete())
+ {
+ m_delete.push_back(p);
+ }
+ return;
+ }
+ if (m_add.find(p -> GetSocket()) != m_add.end())
+ {
+ LogError(p, "Add", (int)p -> GetSocket(), "Attempt to add socket already in add queue", LOG_LEVEL_FATAL);
+ m_delete.push_back(p);
+ return;
+ }
+ m_add[p -> GetSocket()] = p;
+}
+
+
+void SocketHandler::Get(SOCKET s,bool& r,bool& w,bool& e)
+{
+ if (s >= 0)
+ {
+ r = FD_ISSET(s, &m_rfds) ? true : false;
+ w = FD_ISSET(s, &m_wfds) ? true : false;
+ e = FD_ISSET(s, &m_efds) ? true : false;
+ }
+}
+
+
+void SocketHandler::Set(SOCKET s,bool bRead,bool bWrite,bool bException)
+{
+DEB( fprintf(stderr, "Set(%d, %s, %s, %s)\n", s, bRead ? "true" : "false", bWrite ? "true" : "false", bException ? "true" : "false");)
+ if (s >= 0)
+ {
+ if (bRead)
+ {
+ if (!FD_ISSET(s, &m_rfds))
+ {
+ FD_SET(s, &m_rfds);
+ }
+ }
+ else
+ {
+ FD_CLR(s, &m_rfds);
+ }
+ if (bWrite)
+ {
+ if (!FD_ISSET(s, &m_wfds))
+ {
+ FD_SET(s, &m_wfds);
+ }
+ }
+ else
+ {
+ FD_CLR(s, &m_wfds);
+ }
+ if (bException)
+ {
+ if (!FD_ISSET(s, &m_efds))
+ {
+ FD_SET(s, &m_efds);
+ }
+ }
+ else
+ {
+ FD_CLR(s, &m_efds);
+ }
+ }
+}
+
+
+int SocketHandler::Select(long sec,long usec)
+{
+ struct timeval tv;
+ tv.tv_sec = sec;
+ tv.tv_usec = usec;
+ return Select(&tv);
+}
+
+
+int SocketHandler::Select()
+{
+ if (m_fds_callonconnect.size() ||
+#ifdef ENABLE_DETACH
+ (!m_slave && m_fds_detach.size()) ||
+#endif
+ m_fds_timeout.size() ||
+ m_fds_retry.size() ||
+ m_fds_close.size() ||
+ m_fds_erase.size())
+ {
+ return Select(0, 200000);
+ }
+ return Select(NULL);
+}
+
+
+int SocketHandler::Select(struct timeval *tsel)
+{
+ size_t ignore = 0;
+ while (m_add.size() > ignore)
+ {
+ if (m_sockets.size() >= FD_SETSIZE)
+ {
+ LogError(NULL, "Select", (int)m_sockets.size(), "FD_SETSIZE reached", LOG_LEVEL_WARNING);
+ break;
+ }
+ socket_m::iterator it = m_add.begin();
+ SOCKET s = it -> first;
+ Socket *p = it -> second;
+DEB( fprintf(stderr, "Trying to add fd %d, m_add.size() %d, ignore %d\n", (int)s, (int)m_add.size(), (int)ignore);)
+ //
+ if (m_sockets.find(p -> GetSocket()) != m_sockets.end())
+ {
+ LogError(p, "Add", (int)p -> GetSocket(), "Attempt to add socket already in controlled queue", LOG_LEVEL_FATAL);
+ // %! it's a dup, don't add to delete queue, just ignore it
+ m_delete.push_back(p);
+ m_add.erase(it);
+// ignore++;
+ continue;
+ }
+ if (!p -> CloseAndDelete())
+ {
+ StreamSocket *scp = dynamic_cast<StreamSocket *>(p);
+ if (scp && scp -> Connecting()) // 'Open' called before adding socket
+ {
+ Set(s,false,true);
+ }
+ else
+ {
+ TcpSocket *tcp = dynamic_cast<TcpSocket *>(p);
+ bool bWrite = tcp ? tcp -> GetOutputLength() != 0 : false;
+ if (p -> IsDisableRead())
+ {
+ Set(s, false, bWrite);
+ }
+ else
+ {
+ Set(s, true, bWrite);
+ }
+ }
+ m_maxsock = (s > m_maxsock) ? s : m_maxsock;
+ }
+ else
+ {
+ LogError(p, "Add", (int)p -> GetSocket(), "Trying to add socket with SetCloseAndDelete() true", LOG_LEVEL_WARNING);
+ }
+ // only add to m_fds (process fd_set events) if
+ // slave handler and detached/detaching socket
+ // master handler and non-detached socket
+#ifdef ENABLE_DETACH
+ if (!(m_slave ^ p -> IsDetach()))
+#endif
+ {
+ m_fds.push_back(s);
+ }
+ m_sockets[s] = p;
+ //
+ m_add.erase(it);
+ }
+#ifdef MACOSX
+ fd_set rfds;
+ fd_set wfds;
+ fd_set efds;
+ FD_COPY(&m_rfds, &rfds);
+ FD_COPY(&m_wfds, &wfds);
+ FD_COPY(&m_efds, &efds);
+#else
+ fd_set rfds = m_rfds;
+ fd_set wfds = m_wfds;
+ fd_set efds = m_efds;
+#endif
+ int n;
+ if (m_b_use_mutex)
+ {
+ m_mutex.Unlock();
+ n = select( (int)(m_maxsock + 1),&rfds,&wfds,&efds,tsel);
+ m_mutex.Lock();
+ }
+ else
+ {
+ n = select( (int)(m_maxsock + 1),&rfds,&wfds,&efds,tsel);
+ }
+ if (n == -1)
+ {
+ /*
+ EBADF An invalid file descriptor was given in one of the sets.
+ EINTR A non blocked signal was caught.
+ EINVAL n is negative. Or struct timeval contains bad time values (<0).
+ ENOMEM select was unable to allocate memory for internal tables.
+ */
+ if (Errno != m_preverror || m_errcnt++ % 10000 == 0)
+ {
+ LogError(NULL, "select", Errno, StrError(Errno));
+DEB( fprintf(stderr, "m_maxsock: %d\n", m_maxsock);
+ fprintf(stderr, "%s\n", Errno == EINVAL ? "EINVAL" :
+ Errno == EINTR ? "EINTR" :
+ Errno == EBADF ? "EBADF" :
+ Errno == ENOMEM ? "ENOMEM" : "<another>");
+ // test bad fd
+ for (SOCKET i = 0; i <= m_maxsock; i++)
+ {
+ bool t = false;
+ FD_ZERO(&rfds);
+ FD_ZERO(&wfds);
+ FD_ZERO(&efds);
+ if (FD_ISSET(i, &m_rfds))
+ {
+ FD_SET(i, &rfds);
+ t = true;
+ }
+ if (FD_ISSET(i, &m_wfds))
+ {
+ FD_SET(i, &wfds);
+ t = true;
+ }
+ if (FD_ISSET(i, &m_efds))
+ {
+ FD_SET(i, &efds);
+ t = true;
+ }
+ if (t && m_sockets.find(i) == m_sockets.end())
+ {
+ fprintf(stderr, "Bad fd in fd_set: %d\n", i);
+ }
+ }
+) // DEB
+ m_preverror = Errno;
+ }
+ /// \todo rebuild fd_set's from active sockets list (m_sockets) here
+ }
+ else
+ if (!n)
+ {
+ m_preverror = -1;
+ }
+ else
+ if (n > 0)
+ {
+ for (socket_v::iterator it2 = m_fds.begin(); it2 != m_fds.end() && n; it2++)
+ {
+ SOCKET i = *it2;
+ if (FD_ISSET(i, &rfds))
+ {
+ socket_m::iterator itmp = m_sockets.find(i);
+ if (itmp != m_sockets.end()) // found
+ {
+ Socket *p = itmp -> second;
+ // new SSL negotiate method
+#ifdef HAVE_OPENSSL
+ if (p -> IsSSLNegotiate())
+ {
+ p -> SSLNegotiate();
+ }
+ else
+#endif
+ {
+ p -> OnRead();
+ }
+ }
+ else
+ {
+ LogError(NULL, "GetSocket/handler/1", (int)i, "Did not find expected socket using file descriptor", LOG_LEVEL_WARNING);
+ }
+ n--;
+ }
+ if (FD_ISSET(i, &wfds))
+ {
+ socket_m::iterator itmp = m_sockets.find(i);
+ if (itmp != m_sockets.end()) // found
+ {
+ Socket *p = itmp -> second;
+ // new SSL negotiate method
+#ifdef HAVE_OPENSSL
+ if (p -> IsSSLNegotiate())
+ {
+ p -> SSLNegotiate();
+ }
+ else
+#endif
+ {
+ p -> OnWrite();
+ }
+ }
+ else
+ {
+ LogError(NULL, "GetSocket/handler/2", (int)i, "Did not find expected socket using file descriptor", LOG_LEVEL_WARNING);
+ }
+ n--;
+ }
+ if (FD_ISSET(i, &efds))
+ {
+ socket_m::iterator itmp = m_sockets.find(i);
+ if (itmp != m_sockets.end()) // found
+ {
+ Socket *p = itmp -> second;
+ p -> OnException();
+ }
+ else
+ {
+ LogError(NULL, "GetSocket/handler/3", (int)i, "Did not find expected socket using file descriptor", LOG_LEVEL_WARNING);
+ }
+ n--;
+ }
+ } // m_fds loop
+ m_preverror = -1;
+ } // if (n > 0)
+
+ // check CallOnConnect - EVENT
+ if (m_fds_callonconnect.size())
+ {
+ socket_v tmp = m_fds_callonconnect;
+ for (socket_v::iterator it = tmp.begin(); it != tmp.end(); it++)
+ {
+ Socket *p = NULL;
+ {
+ socket_m::iterator itmp = m_sockets.find(*it);
+ if (itmp != m_sockets.end()) // found
+ {
+ p = itmp -> second;
+ }
+ else
+ {
+ LogError(NULL, "GetSocket/handler/4", (int)*it, "Did not find expected socket using file descriptor", LOG_LEVEL_WARNING);
+ }
+ }
+ if (p)
+ {
+// if (p -> CallOnConnect() && p -> Ready() )
+ {
+ p -> SetConnected(); // moved here from inside if (tcp) check below
+#ifdef HAVE_OPENSSL
+ if (p -> IsSSL()) // SSL Enabled socket
+ p -> OnSSLConnect();
+ else
+#endif
+#ifdef ENABLE_SOCKS4
+ if (p -> Socks4())
+ p -> OnSocks4Connect();
+ else
+#endif
+ {
+ TcpSocket *tcp = dynamic_cast<TcpSocket *>(p);
+ if (tcp)
+ {
+ if (tcp -> GetOutputLength())
+ {
+ p -> OnWrite();
+ }
+ }
+#ifdef ENABLE_RECONNECT
+ if (tcp && tcp -> IsReconnect())
+ p -> OnReconnect();
+ else
+#endif
+ {
+// LogError(p, "Calling OnConnect", 0, "Because CallOnConnect", LOG_LEVEL_INFO);
+ p -> OnConnect();
+ }
+ }
+// p -> SetCallOnConnect( false );
+ AddList(p -> GetSocket(), LIST_CALLONCONNECT, false);
+ }
+ }
+ }
+ }
+#ifdef ENABLE_DETACH
+ // check detach of socket if master handler - EVENT
+ if (!m_slave && m_fds_detach.size())
+ {
+ // %! why not using tmp list here??!?
+ for (socket_v::iterator it = m_fds_detach.begin(); it != m_fds_detach.end(); it++)
+ {
+ Socket *p = NULL;
+ {
+ socket_m::iterator itmp = m_sockets.find(*it);
+ if (itmp != m_sockets.end()) // found
+ {
+ p = itmp -> second;
+ }
+ else
+ {
+ LogError(NULL, "GetSocket/handler/5", (int)*it, "Did not find expected socket using file descriptor", LOG_LEVEL_WARNING);
+ }
+ }
+ if (p)
+ {
+// if (p -> IsDetach())
+ {
+ Set(p -> GetSocket(), false, false, false);
+ // After DetachSocket(), all calls to Handler() will return a reference
+ // to the new slave SocketHandler running in the new thread.
+ p -> DetachSocket();
+ // Adding the file descriptor to m_fds_erase will now also remove the
+ // socket from the detach queue - tnx knightmad
+ m_fds_erase.push_back(p -> GetSocket());
+ }
+ }
+ }
+ }
+#endif
+ // check Connecting - connection timeout - conditional event
+ if (m_fds_timeout.size())
+ {
+ time_t tnow = time(NULL);
+ if (tnow != m_tlast)
+ {
+ socket_v tmp = m_fds_timeout;
+DEB( fprintf(stderr, "Checking %d socket(s) for timeout\n", tmp.size());)
+ for (socket_v::iterator it = tmp.begin(); it != tmp.end(); it++)
+ {
+ Socket *p = NULL;
+ {
+ socket_m::iterator itmp = m_sockets.find(*it);
+ if (itmp != m_sockets.end()) // found
+ {
+ p = itmp -> second;
+ }
+ else
+ {
+ itmp = m_add.find(*it);
+ if (itmp != m_add.end())
+ {
+ p = itmp -> second;
+ }
+ else
+ {
+ LogError(NULL, "GetSocket/handler/6", (int)*it, "Did not find expected socket using file descriptor", LOG_LEVEL_WARNING);
+ }
+ }
+ }
+ if (p)
+ {
+ if (p -> Timeout(tnow))
+ {
+ StreamSocket *scp = dynamic_cast<StreamSocket *>(p);
+ if (scp && scp -> Connecting())
+ p -> OnConnectTimeout();
+ else
+ p -> OnTimeout();
+ p -> SetTimeout(0);
+ }
+ }
+ }
+ m_tlast = tnow;
+ } // tnow != tlast
+ }
+ // check retry client connect - EVENT
+ if (m_fds_retry.size())
+ {
+ socket_v tmp = m_fds_retry;
+ for (socket_v::iterator it = tmp.begin(); it != tmp.end(); it++)
+ {
+ Socket *p = NULL;
+ {
+ socket_m::iterator itmp = m_sockets.find(*it);
+ if (itmp != m_sockets.end()) // found
+ {
+ p = itmp -> second;
+ }
+ else
+ {
+ LogError(NULL, "GetSocket/handler/7", (int)*it, "Did not find expected socket using file descriptor", LOG_LEVEL_WARNING);
+ }
+ }
+ if (p)
+ {
+// if (p -> RetryClientConnect())
+ {
+ TcpSocket *tcp = dynamic_cast<TcpSocket *>(p);
+ SOCKET nn = *it; //(*it3).first;
+ tcp -> SetRetryClientConnect(false);
+DEB( fprintf(stderr, "Close() before retry client connect\n");)
+ p -> Close(); // removes from m_fds_retry
+ std::auto_ptr<SocketAddress> ad = p -> GetClientRemoteAddress();
+ if (ad.get())
+ {
+ tcp -> Open(*ad);
+ }
+ else
+ {
+ LogError(p, "RetryClientConnect", 0, "no address", LOG_LEVEL_ERROR);
+ }
+ Add(p);
+ m_fds_erase.push_back(nn);
+ }
+ }
+ }
+ }
+ // check close and delete - conditional event
+ if (m_fds_close.size())
+ {
+ socket_v tmp = m_fds_close;
+DEB( fprintf(stderr, "m_fds_close.size() == %d\n", (int)m_fds_close.size());)
+ for (socket_v::iterator it = tmp.begin(); it != tmp.end(); it++)
+ {
+ Socket *p = NULL;
+ {
+ socket_m::iterator itmp = m_sockets.find(*it);
+ if (itmp != m_sockets.end()) // found
+ {
+ p = itmp -> second;
+ }
+ else
+ {
+ itmp = m_add.find(*it);
+ if (itmp != m_add.end())
+ {
+ p = itmp -> second;
+ }
+ else
+ {
+ LogError(NULL, "GetSocket/handler/8", (int)*it, "Did not find expected socket using file descriptor", LOG_LEVEL_WARNING);
+ }
+ }
+ }
+ if (p)
+ {
+// if (p -> CloseAndDelete() )
+ {
+ TcpSocket *tcp = dynamic_cast<TcpSocket *>(p);
+ // new graceful tcp - flush and close timeout 5s
+ if (tcp && p -> IsConnected() && tcp -> GetFlushBeforeClose() &&
+#ifdef HAVE_OPENSSL
+ !tcp -> IsSSL() &&
+#endif
+ p -> TimeSinceClose() < 5)
+ {
+DEB( fprintf(stderr, " close(1)\n");)
+ if (tcp -> GetOutputLength())
+ {
+ LogError(p, "Closing", (int)tcp -> GetOutputLength(), "Sending all data before closing", LOG_LEVEL_INFO);
+ }
+ else // shutdown write when output buffer is empty
+ if (!(tcp -> GetShutdown() & SHUT_WR))
+ {
+ SOCKET nn = *it;
+ if (nn != INVALID_SOCKET && shutdown(nn, SHUT_WR) == -1)
+ {
+ LogError(p, "graceful shutdown", Errno, StrError(Errno), LOG_LEVEL_ERROR);
+ }
+ tcp -> SetShutdown(SHUT_WR);
+ }
+ }
+ else
+#ifdef ENABLE_RECONNECT
+ if (tcp && p -> IsConnected() && tcp -> Reconnect())
+ {
+ SOCKET nn = *it; //(*it3).first;
+DEB( fprintf(stderr, " close(2) fd %d\n", nn);)
+ p -> SetCloseAndDelete(false);
+ tcp -> SetIsReconnect();
+ p -> SetConnected(false);
+DEB( fprintf(stderr, "Close() before reconnect\n");)
+ p -> Close(); // dispose of old file descriptor (Open creates a new)
+ p -> OnDisconnect();
+ std::auto_ptr<SocketAddress> ad = p -> GetClientRemoteAddress();
+ if (ad.get())
+ {
+ tcp -> Open(*ad);
+ }
+ else
+ {
+ LogError(p, "Reconnect", 0, "no address", LOG_LEVEL_ERROR);
+ }
+ tcp -> ResetConnectionRetries();
+ Add(p);
+ m_fds_erase.push_back(nn);
+ }
+ else
+#endif
+ {
+ SOCKET nn = *it; //(*it3).first;
+DEB( fprintf(stderr, " close(3) fd %d GetSocket() %d\n", nn, p -> GetSocket());)
+ if (tcp && p -> IsConnected() && tcp -> GetOutputLength())
+ {
+ LogError(p, "Closing", (int)tcp -> GetOutputLength(), "Closing socket while data still left to send", LOG_LEVEL_WARNING);
+ }
+#ifdef ENABLE_POOL
+ if (p -> Retain() && !p -> Lost())
+ {
+ PoolSocket *p2 = new PoolSocket(*this, p);
+ p2 -> SetDeleteByHandler();
+ Add(p2);
+ //
+ p -> SetCloseAndDelete(false); // added - remove from m_fds_close
+ }
+ else
+#endif // ENABLE_POOL
+ {
+ Set(p -> GetSocket(),false,false,false);
+DEB( fprintf(stderr, "Close() before OnDelete\n");)
+ p -> Close();
+ }
+ p -> OnDelete();
+ if (p -> DeleteByHandler())
+ {
+ p -> SetErasedByHandler();
+ }
+ m_fds_erase.push_back(nn);
+ }
+ }
+ }
+ }
+ }
+
+ // check erased sockets
+ bool check_max_fd = false;
+ while (m_fds_erase.size())
+ {
+ socket_v::iterator it = m_fds_erase.begin();
+ SOCKET nn = *it;
+#ifdef ENABLE_DETACH
+ {
+ for (socket_v::iterator it = m_fds_detach.begin(); it != m_fds_detach.end(); it++)
+ {
+ if (*it == nn)
+ {
+ m_fds_detach.erase(it);
+ break;
+ }
+ }
+ }
+#endif
+ {
+ for (socket_v::iterator it = m_fds.begin(); it != m_fds.end(); it++)
+ {
+ if (*it == nn)
+ {
+ m_fds.erase(it);
+ break;
+ }
+ }
+ }
+ {
+ socket_m::iterator it = m_sockets.find(nn);
+ if (it != m_sockets.end())
+ {
+ Socket *p = it -> second;
+ /* Sometimes a SocketThread class can finish its run before the master
+ sockethandler gets here. In that case, the SocketThread has set the
+ 'ErasedByHandler' flag on the socket which will make us end up with a
+ double delete on the socket instance.
+ The fix is to make sure that the master sockethandler only can delete
+ non-detached sockets, and a slave sockethandler only can delete
+ detach sockets. */
+ if (p -> ErasedByHandler()
+#ifdef ENABLE_DETACH
+ && !(m_slave ^ p -> IsDetached())
+#endif
+ )
+ {
+#ifdef ENABLE_TRIGGERS
+ bool again = false;
+ do
+ {
+ again = false;
+ for (std::map<int, Socket *>::iterator it = m_trigger_src.begin(); it != m_trigger_src.end(); it++)
+ {
+ int id = it -> first;
+ Socket *src = it -> second;
+ if (src == p)
+ {
+ for (std::map<Socket *, bool>::iterator it = m_trigger_dst[id].begin(); it != m_trigger_dst[id].end(); it++)
+ {
+ Socket *dst = it -> first;
+ if (Valid(dst))
+ {
+ dst -> OnCancelled(id);
+ }
+ }
+ m_trigger_src.erase(m_trigger_src.find(id));
+ m_trigger_dst.erase(m_trigger_dst.find(id));
+ again = true;
+ break;
+ }
+ }
+ } while (again);
+#endif
+ delete p;
+ }
+ m_sockets.erase(it);
+ }
+ }
+ m_fds_erase.erase(it);
+ check_max_fd = true;
+ }
+ // calculate max file descriptor for select() call
+ if (check_max_fd)
+ {
+ m_maxsock = 0;
+ for (socket_v::iterator it = m_fds.begin(); it != m_fds.end(); it++)
+ {
+ SOCKET s = *it;
+ m_maxsock = s > m_maxsock ? s : m_maxsock;
+ }
+ }
+ // remove Add's that fizzed
+ while (m_delete.size())
+ {
+ std::list<Socket *>::iterator it = m_delete.begin();
+ Socket *p = *it;
+ p -> OnDelete();
+ m_delete.erase(it);
+ if (p -> DeleteByHandler()
+#ifdef ENABLE_DETACH
+ && !(m_slave ^ p -> IsDetached())
+#endif
+ )
+ {
+ p -> SetErasedByHandler();
+#ifdef ENABLE_TRIGGERS
+ bool again = false;
+ do
+ {
+ again = false;
+ for (std::map<int, Socket *>::iterator it = m_trigger_src.begin(); it != m_trigger_src.end(); it++)
+ {
+ int id = it -> first;
+ Socket *src = it -> second;
+ if (src == p)
+ {
+ for (std::map<Socket *, bool>::iterator it = m_trigger_dst[id].begin(); it != m_trigger_dst[id].end(); it++)
+ {
+ Socket *dst = it -> first;
+ if (Valid(dst))
+ {
+ dst -> OnCancelled(id);
+ }
+ }
+ m_trigger_src.erase(m_trigger_src.find(id));
+ m_trigger_dst.erase(m_trigger_dst.find(id));
+ again = true;
+ break;
+ }
+ }
+ } while (again);
+#endif
+ delete p;
+ }
+ }
+ return n;
+}
+
+
+#ifdef ENABLE_RESOLVER
+bool SocketHandler::Resolving(Socket *p0)
+{
+ std::map<Socket *, bool>::iterator it = m_resolve_q.find(p0);
+ return it != m_resolve_q.end();
+}
+#endif
+
+
+bool SocketHandler::Valid(Socket *p0)
+{
+ for (socket_m::iterator it = m_sockets.begin(); it != m_sockets.end(); it++)
+ {
+ Socket *p = it -> second;
+ if (p0 == p)
+ return true;
+ }
+ return false;
+}
+
+
+bool SocketHandler::OkToAccept(Socket *)
+{
+ return true;
+}
+
+
+size_t SocketHandler::GetCount()
+{
+/*
+printf(" m_sockets : %d\n", m_sockets.size());
+printf(" m_add : %d\n", m_add.size());
+printf(" m_delete : %d\n", m_delete.size());
+*/
+ return m_sockets.size() + m_add.size() + m_delete.size();
+}
+
+
+#ifdef ENABLE_SOCKS4
+void SocketHandler::SetSocks4Host(ipaddr_t a)
+{
+ m_socks4_host = a;
+}
+
+
+void SocketHandler::SetSocks4Host(const std::string& host)
+{
+ Utility::u2ip(host, m_socks4_host);
+}
+
+
+void SocketHandler::SetSocks4Port(port_t port)
+{
+ m_socks4_port = port;
+}
+
+
+void SocketHandler::SetSocks4Userid(const std::string& id)
+{
+ m_socks4_userid = id;
+}
+#endif
+
+
+#ifdef ENABLE_RESOLVER
+int SocketHandler::Resolve(Socket *p,const std::string& host,port_t port)
+{
+ // check cache
+ ResolvSocket *resolv = new ResolvSocket(*this, p, host, port);
+ resolv -> SetId(++m_resolv_id);
+ resolv -> SetDeleteByHandler();
+ ipaddr_t local;
+ Utility::u2ip("127.0.0.1", local);
+ if (!resolv -> Open(local, m_resolver_port))
+ {
+ LogError(resolv, "Resolve", -1, "Can't connect to local resolve server", LOG_LEVEL_FATAL);
+ }
+ Add(resolv);
+ m_resolve_q[p] = true;
+DEB( fprintf(stderr, " *** Resolve '%s:%d' id#%d m_resolve_q size: %d p: %p\n", host.c_str(), port, resolv -> GetId(), m_resolve_q.size(), p);)
+ return resolv -> GetId();
+}
+
+
+#ifdef ENABLE_IPV6
+int SocketHandler::Resolve6(Socket *p,const std::string& host,port_t port)
+{
+ // check cache
+ ResolvSocket *resolv = new ResolvSocket(*this, p, host, port, true);
+ resolv -> SetId(++m_resolv_id);
+ resolv -> SetDeleteByHandler();
+ ipaddr_t local;
+ Utility::u2ip("127.0.0.1", local);
+ if (!resolv -> Open(local, m_resolver_port))
+ {
+ LogError(resolv, "Resolve", -1, "Can't connect to local resolve server", LOG_LEVEL_FATAL);
+ }
+ Add(resolv);
+ m_resolve_q[p] = true;
+ return resolv -> GetId();
+}
+#endif
+
+
+int SocketHandler::Resolve(Socket *p,ipaddr_t a)
+{
+ // check cache
+ ResolvSocket *resolv = new ResolvSocket(*this, p, a);
+ resolv -> SetId(++m_resolv_id);
+ resolv -> SetDeleteByHandler();
+ ipaddr_t local;
+ Utility::u2ip("127.0.0.1", local);
+ if (!resolv -> Open(local, m_resolver_port))
+ {
+ LogError(resolv, "Resolve", -1, "Can't connect to local resolve server", LOG_LEVEL_FATAL);
+ }
+ Add(resolv);
+ m_resolve_q[p] = true;
+ return resolv -> GetId();
+}
+
+
+#ifdef ENABLE_IPV6
+int SocketHandler::Resolve(Socket *p,in6_addr& a)
+{
+ // check cache
+ ResolvSocket *resolv = new ResolvSocket(*this, p, a);
+ resolv -> SetId(++m_resolv_id);
+ resolv -> SetDeleteByHandler();
+ ipaddr_t local;
+ Utility::u2ip("127.0.0.1", local);
+ if (!resolv -> Open(local, m_resolver_port))
+ {
+ LogError(resolv, "Resolve", -1, "Can't connect to local resolve server", LOG_LEVEL_FATAL);
+ }
+ Add(resolv);
+ m_resolve_q[p] = true;
+ return resolv -> GetId();
+}
+#endif
+
+
+void SocketHandler::EnableResolver(port_t port)
+{
+ if (!m_resolver)
+ {
+ m_resolver_port = port;
+ m_resolver = new ResolvServer(port);
+ }
+}
+
+
+bool SocketHandler::ResolverReady()
+{
+ return m_resolver ? m_resolver -> Ready() : false;
+}
+#endif // ENABLE_RESOLVER
+
+
+#ifdef ENABLE_SOCKS4
+void SocketHandler::SetSocks4TryDirect(bool x)
+{
+ m_bTryDirect = x;
+}
+
+
+ipaddr_t SocketHandler::GetSocks4Host()
+{
+ return m_socks4_host;
+}
+
+
+port_t SocketHandler::GetSocks4Port()
+{
+ return m_socks4_port;
+}
+
+
+const std::string& SocketHandler::GetSocks4Userid()
+{
+ return m_socks4_userid;
+}
+
+
+bool SocketHandler::Socks4TryDirect()
+{
+ return m_bTryDirect;
+}
+#endif
+
+
+#ifdef ENABLE_RESOLVER
+bool SocketHandler::ResolverEnabled()
+{
+ return m_resolver ? true : false;
+}
+
+
+port_t SocketHandler::GetResolverPort()
+{
+ return m_resolver_port;
+}
+#endif // ENABLE_RESOLVER
+
+
+#ifdef ENABLE_POOL
+ISocketHandler::PoolSocket *SocketHandler::FindConnection(int type,const std::string& protocol,SocketAddress& ad)
+{
+ for (socket_m::iterator it = m_sockets.begin(); it != m_sockets.end() && m_sockets.size(); it++)
+ {
+ PoolSocket *pools = dynamic_cast<PoolSocket *>(it -> second);
+ if (pools)
+ {
+ if (pools -> GetSocketType() == type &&
+ pools -> GetSocketProtocol() == protocol &&
+// %! pools -> GetClientRemoteAddress() &&
+ *pools -> GetClientRemoteAddress() == ad)
+ {
+ m_sockets.erase(it);
+ pools -> SetRetain(); // avoid Close in Socket destructor
+ return pools; // Caller is responsible that this socket is deleted
+ }
+ }
+ }
+ return NULL;
+}
+
+
+void SocketHandler::EnablePool(bool x)
+{
+ m_b_enable_pool = x;
+}
+
+
+bool SocketHandler::PoolEnabled()
+{
+ return m_b_enable_pool;
+}
+#endif
+
+
+void SocketHandler::Remove(Socket *p)
+{
+#ifdef ENABLE_RESOLVER
+ std::map<Socket *, bool>::iterator it4 = m_resolve_q.find(p);
+ if (it4 != m_resolve_q.end())
+ m_resolve_q.erase(it4);
+#endif
+ if (p -> ErasedByHandler())
+ {
+ return;
+ }
+ for (socket_m::iterator it = m_sockets.begin(); it != m_sockets.end(); it++)
+ {
+ if (it -> second == p)
+ {
+ LogError(p, "Remove", -1, "Socket destructor called while still in use", LOG_LEVEL_WARNING);
+ m_sockets.erase(it);
+ return;
+ }
+ }
+ for (socket_m::iterator it2 = m_add.begin(); it2 != m_add.end(); it2++)
+ {
+ if ((*it2).second == p)
+ {
+ LogError(p, "Remove", -2, "Socket destructor called while still in use", LOG_LEVEL_WARNING);
+ m_add.erase(it2);
+ return;
+ }
+ }
+ for (std::list<Socket *>::iterator it3 = m_delete.begin(); it3 != m_delete.end(); it3++)
+ {
+ if (*it3 == p)
+ {
+ LogError(p, "Remove", -3, "Socket destructor called while still in use", LOG_LEVEL_WARNING);
+ m_delete.erase(it3);
+ return;
+ }
+ }
+}
+
+
+void SocketHandler::CheckSanity()
+{
+ CheckList(m_fds, "active sockets"); // active sockets
+ CheckList(m_fds_erase, "sockets to be erased"); // should always be empty anyway
+ CheckList(m_fds_callonconnect, "checklist CallOnConnect");
+#ifdef ENABLE_DETACH
+ CheckList(m_fds_detach, "checklist Detach");
+#endif
+ CheckList(m_fds_timeout, "checklist Timeout");
+ CheckList(m_fds_retry, "checklist retry client connect");
+ CheckList(m_fds_close, "checklist close and delete");
+}
+
+
+void SocketHandler::CheckList(socket_v& ref,const std::string& listname)
+{
+ for (socket_v::iterator it = ref.begin(); it != ref.end(); it++)
+ {
+ SOCKET s = *it;
+ if (m_sockets.find(s) != m_sockets.end())
+ continue;
+ if (m_add.find(s) != m_add.end())
+ continue;
+ bool found = false;
+ for (std::list<Socket *>::iterator it = m_delete.begin(); it != m_delete.end(); it++)
+ {
+ Socket *p = *it;
+ if (p -> GetSocket() == s)
+ {
+ found = true;
+ break;
+ }
+ }
+ if (!found)
+ {
+ fprintf(stderr, "CheckList failed for \"%s\": fd %d\n", listname.c_str(), s);
+ }
+ }
+}
+
+
+void SocketHandler::AddList(SOCKET s,list_t which_one,bool add)
+{
+ if (s == INVALID_SOCKET)
+ {
+DEB( fprintf(stderr, "AddList: invalid_socket\n");)
+ return;
+ }
+ socket_v& ref =
+ (which_one == LIST_CALLONCONNECT) ? m_fds_callonconnect :
+#ifdef ENABLE_DETACH
+ (which_one == LIST_DETACH) ? m_fds_detach :
+#endif
+ (which_one == LIST_TIMEOUT) ? m_fds_timeout :
+ (which_one == LIST_RETRY) ? m_fds_retry :
+ (which_one == LIST_CLOSE) ? m_fds_close : m_fds_close;
+ if (add)
+ {
+#ifdef ENABLE_DETACH
+DEB( fprintf(stderr, "AddList; %5d: %s: %s\n", s, (which_one == LIST_CALLONCONNECT) ? "CallOnConnect" :
+ (which_one == LIST_DETACH) ? "Detach" :
+ (which_one == LIST_TIMEOUT) ? "Timeout" :
+ (which_one == LIST_RETRY) ? "Retry" :
+ (which_one == LIST_CLOSE) ? "Close" : "<undef>",
+ add ? "Add" : "Remove");)
+#else
+DEB( fprintf(stderr, "AddList; %5d: %s: %s\n", s, (which_one == LIST_CALLONCONNECT) ? "CallOnConnect" :
+ (which_one == LIST_TIMEOUT) ? "Timeout" :
+ (which_one == LIST_RETRY) ? "Retry" :
+ (which_one == LIST_CLOSE) ? "Close" : "<undef>",
+ add ? "Add" : "Remove");)
+#endif
+ }
+ if (add)
+ {
+ for (socket_v::iterator it = ref.begin(); it != ref.end(); it++)
+ {
+ if (*it == s) // already there
+ {
+ return;
+ }
+ }
+ ref.push_back(s);
+ return;
+ }
+ // remove
+ for (socket_v::iterator it = ref.begin(); it != ref.end(); it++)
+ {
+ if (*it == s)
+ {
+ ref.erase(it);
+ break;
+ }
+ }
+//DEB( fprintf(stderr, "/AddList\n");)
+}
+
+
+#ifdef ENABLE_TRIGGERS
+int SocketHandler::TriggerID(Socket *src)
+{
+ int id = m_next_trigger_id++;
+ m_trigger_src[id] = src;
+ return id;
+}
+
+
+bool SocketHandler::Subscribe(int id, Socket *dst)
+{
+ if (m_trigger_src.find(id) != m_trigger_src.end())
+ {
+ std::map<Socket *, bool>::iterator it = m_trigger_dst[id].find(dst);
+ if (it != m_trigger_dst[id].end())
+ {
+ m_trigger_dst[id][dst] = true;
+ return true;
+ }
+ LogError(dst, "Subscribe", id, "Already subscribed", LOG_LEVEL_INFO);
+ return false;
+ }
+ LogError(dst, "Subscribe", id, "Trigger id not found", LOG_LEVEL_INFO);
+ return false;
+}
+
+
+bool SocketHandler::Unsubscribe(int id, Socket *dst)
+{
+ if (m_trigger_src.find(id) != m_trigger_src.end())
+ {
+ std::map<Socket *, bool>::iterator it = m_trigger_dst[id].find(dst);
+ if (it != m_trigger_dst[id].end())
+ {
+ m_trigger_dst[id].erase(it);
+ return true;
+ }
+ LogError(dst, "Unsubscribe", id, "Not subscribed", LOG_LEVEL_INFO);
+ return false;
+ }
+ LogError(dst, "Unsubscribe", id, "Trigger id not found", LOG_LEVEL_INFO);
+ return false;
+}
+
+
+void SocketHandler::Trigger(int id, Socket::TriggerData& data, bool erase)
+{
+ if (m_trigger_src.find(id) != m_trigger_src.end())
+ {
+ data.SetSource( m_trigger_src[id] );
+ for (std::map<Socket *, bool>::iterator it = m_trigger_dst[id].begin(); it != m_trigger_dst[id].end(); it++)
+ {
+ Socket *dst = it -> first;
+ if (Valid(dst))
+ {
+ dst -> OnTrigger(id, data);
+ }
+ }
+ if (erase)
+ {
+ m_trigger_src.erase(m_trigger_src.find(id));
+ m_trigger_dst.erase(m_trigger_dst.find(id));
+ }
+ }
+ else
+ {
+ LogError(NULL, "Trigger", id, "Trigger id not found", LOG_LEVEL_INFO);
+ }
+}
+#endif // ENABLE_TRIGGERS
+
+
+#ifdef SOCKETS_NAMESPACE
+}
+#endif
+
diff --git a/Sockets/SocketHandler.h b/Sockets/SocketHandler.h
new file mode 100644
index 0000000..c7e20df
--- /dev/null
+++ b/Sockets/SocketHandler.h
@@ -0,0 +1,266 @@
+/** \file SocketHandler.h
+ ** \date 2004-02-13
+ ** \author grymse@alhem.net
+**/
+/*
+Copyright (C) 2004-2007 Anders Hedstrom
+
+This library is made available under the terms of the GNU GPL.
+
+If you would like to use this library in a closed-source application,
+a separate license agreement is available. For information about
+the closed-source license agreement for the C++ sockets library,
+please visit http://www.alhem.net/Sockets/license.html and/or
+email license@alhem.net.
+
+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.
+*/
+#ifndef _SOCKETS_SocketHandler_H
+#define _SOCKETS_SocketHandler_H
+
+#include "sockets-config.h"
+#include <map>
+#include <list>
+
+#include "socket_include.h"
+#include "ISocketHandler.h"
+
+#ifdef SOCKETS_NAMESPACE
+namespace SOCKETS_NAMESPACE {
+#endif
+
+
+class Socket;
+#ifdef ENABLE_RESOLVER
+class ResolvServer;
+#endif
+class Mutex;
+
+/** Socket container class, event generator.
+ \ingroup basic */
+class SocketHandler : public ISocketHandler
+{
+protected:
+ /** Map type for holding file descriptors/socket object pointers. */
+ typedef std::map<SOCKET,Socket *> socket_m;
+
+public:
+ /** SocketHandler constructor.
+ \param log Optional log class pointer */
+ SocketHandler(StdLog *log = NULL);
+
+ /** SocketHandler threadsafe constructor.
+ \param mutex Externally declared mutex variable
+ \param log Optional log class pointer */
+ SocketHandler(Mutex& mutex,StdLog *log = NULL);
+
+ ~SocketHandler();
+
+ /** Get mutex reference for threadsafe operations. */
+ Mutex& GetMutex() const;
+
+ /** Register StdLog object for error callback.
+ \param log Pointer to log class */
+ void RegStdLog(StdLog *log);
+
+ /** Log error to log class for print out / storage. */
+ void LogError(Socket *p,const std::string& user_text,int err,const std::string& sys_err,loglevel_t t = LOG_LEVEL_WARNING);
+
+ /** Add socket instance to socket map. Removal is always automatic. */
+ void Add(Socket *);
+
+ /** Get status of read/write/exception file descriptor set for a socket. */
+ void Get(SOCKET s,bool& r,bool& w,bool& e);
+
+ /** Set read/write/exception file descriptor sets (fd_set). */
+ void Set(SOCKET s,bool bRead,bool bWrite,bool bException = true);
+
+ /** Wait for events, generate callbacks. */
+ int Select(long sec,long usec);
+
+ /** This method will not return until an event has been detected. */
+ int Select();
+
+ /** Wait for events, generate callbacks. */
+ int Select(struct timeval *tsel);
+
+ /** Check that a socket really is handled by this socket handler. */
+ bool Valid(Socket *);
+
+ /** Return number of sockets handled by this handler. */
+ size_t GetCount();
+
+ /** Override and return false to deny all incoming connections.
+ \param p ListenSocket class pointer (use GetPort to identify which one) */
+ bool OkToAccept(Socket *p);
+
+ /** Called by Socket when a socket changes state. */
+ void AddList(SOCKET s,list_t which_one,bool add);
+
+ // Connection pool
+#ifdef ENABLE_POOL
+ /** Find available open connection (used by connection pool). */
+ ISocketHandler::PoolSocket *FindConnection(int type,const std::string& protocol,SocketAddress&);
+ /** Enable connection pool (by default disabled). */
+ void EnablePool(bool x = true);
+ /** Check pool status.
+ \return true if connection pool is enabled */
+ bool PoolEnabled();
+#endif // ENABLE_POOL
+
+ // Socks4
+#ifdef ENABLE_SOCKS4
+ /** Set socks4 server ip that all new tcp sockets should use. */
+ void SetSocks4Host(ipaddr_t);
+ /** Set socks4 server hostname that all new tcp sockets should use. */
+ void SetSocks4Host(const std::string& );
+ /** Set socks4 server port number that all new tcp sockets should use. */
+ void SetSocks4Port(port_t);
+ /** Set optional socks4 userid. */
+ void SetSocks4Userid(const std::string& );
+ /** If connection to socks4 server fails, immediately try direct connection to final host. */
+ void SetSocks4TryDirect(bool x = true);
+ /** Get socks4 server ip.
+ \return socks4 server ip */
+ ipaddr_t GetSocks4Host();
+ /** Get socks4 port number.
+ \return socks4 port number */
+ port_t GetSocks4Port();
+ /** Get socks4 userid (optional).
+ \return socks4 userid */
+ const std::string& GetSocks4Userid();
+ /** Check status of socks4 try direct flag.
+ \return true if direct connection should be tried if connection to socks4 server fails */
+ bool Socks4TryDirect();
+#endif // ENABLE_SOCKS4
+
+ // DNS resolve server
+#ifdef ENABLE_RESOLVER
+ /** Enable asynchronous DNS.
+ \param port Listen port of asynchronous dns server */
+ void EnableResolver(port_t port = 16667);
+ /** Check resolver status.
+ \return true if resolver is enabled */
+ bool ResolverEnabled();
+ /** Queue a dns request.
+ \param host Hostname to be resolved
+ \param port Port number will be echoed in Socket::OnResolved callback */
+ int Resolve(Socket *,const std::string& host,port_t port);
+#ifdef ENABLE_IPV6
+ int Resolve6(Socket *,const std::string& host,port_t port);
+#endif
+ /** Do a reverse dns lookup. */
+ int Resolve(Socket *,ipaddr_t a);
+#ifdef ENABLE_IPV6
+ int Resolve(Socket *,in6_addr& a);
+#endif
+ /** Get listen port of asynchronous dns server. */
+ port_t GetResolverPort();
+ /** Resolver thread ready for queries. */
+ bool ResolverReady();
+ /** Returns true if the socket is waiting for a resolve event. */
+ bool Resolving(Socket *);
+#endif // ENABLE_RESOLVER
+
+#ifdef ENABLE_TRIGGERS
+ /** Fetch unique trigger id. */
+ int TriggerID(Socket *src);
+ /** Subscribe socket to trigger id. */
+ bool Subscribe(int id, Socket *dst);
+ /** Unsubscribe socket from trigger id. */
+ bool Unsubscribe(int id, Socket *dst);
+ /** Execute OnTrigger for subscribed sockets.
+ \param id Trigger ID
+ \param data Data passed from source to destination
+ \param erase Empty trigger id source and destination maps if 'true',
+ Leave them in place if 'false' - if a trigger should be called many times */
+ void Trigger(int id, Socket::TriggerData& data, bool erase = true);
+#endif // ENABLE_TRIGGERS
+
+#ifdef ENABLE_DETACH
+ /** Indicates that the handler runs under SocketThread. */
+ void SetSlave(bool x = true);
+ /** Indicates that the handler runs under SocketThread. */
+ bool IsSlave();
+#endif
+
+ /** Sanity check of those accursed lists. */
+ void CheckSanity();
+
+protected:
+ socket_m m_sockets; ///< Active sockets map
+ socket_m m_add; ///< Sockets to be added to sockets map
+ std::list<Socket *> m_delete; ///< Sockets to be deleted (failed when Add)
+
+protected:
+ StdLog *m_stdlog; ///< Registered log class, or NULL
+ Mutex& m_mutex; ///< Thread safety mutex
+ bool m_b_use_mutex; ///< Mutex correctly initialized
+
+private:
+ void CheckList(socket_v&,const std::string&); ///< Used by CheckSanity
+ /** Remove socket from socket map, used by Socket class. */
+ void Remove(Socket *);
+ SOCKET m_maxsock; ///< Highest file descriptor + 1 in active sockets list
+ fd_set m_rfds; ///< file descriptor set monitored for read events
+ fd_set m_wfds; ///< file descriptor set monitored for write events
+ fd_set m_efds; ///< file descriptor set monitored for exceptions
+ int m_preverror; ///< debug select() error
+ int m_errcnt; ///< debug select() error
+ time_t m_tlast; ///< timeout control
+
+ // state lists
+ socket_v m_fds; ///< Active file descriptor list
+ socket_v m_fds_erase; ///< File descriptors that are to be erased from m_sockets
+ socket_v m_fds_callonconnect; ///< checklist CallOnConnect
+#ifdef ENABLE_DETACH
+ socket_v m_fds_detach; ///< checklist Detach
+#endif
+ socket_v m_fds_timeout; ///< checklist timeout
+ socket_v m_fds_retry; ///< checklist retry client connect
+ socket_v m_fds_close; ///< checklist close and delete
+
+#ifdef ENABLE_SOCKS4
+ ipaddr_t m_socks4_host; ///< Socks4 server host ip
+ port_t m_socks4_port; ///< Socks4 server port number
+ std::string m_socks4_userid; ///< Socks4 userid
+ bool m_bTryDirect; ///< Try direct connection if socks4 server fails
+#endif
+#ifdef ENABLE_RESOLVER
+ int m_resolv_id; ///< Resolver id counter
+ ResolvServer *m_resolver; ///< Resolver thread pointer
+ port_t m_resolver_port; ///< Resolver listen port
+ std::map<Socket *, bool> m_resolve_q; ///< resolve queue
+#endif
+#ifdef ENABLE_POOL
+ bool m_b_enable_pool; ///< Connection pool enabled if true
+#endif
+#ifdef ENABLE_TRIGGERS
+ int m_next_trigger_id; ///< Unique trigger id counter
+ std::map<int, Socket *> m_trigger_src; ///< mapping trigger id to source socket
+ std::map<int, std::map<Socket *, bool> > m_trigger_dst; ///< mapping trigger id to destination sockets
+#endif
+#ifdef ENABLE_DETACH
+ bool m_slave; ///< Indicates that this is a ISocketHandler run in SocketThread
+#endif
+};
+
+
+#ifdef SOCKETS_NAMESPACE
+}
+#endif
+
+#endif // _SOCKETS_SocketHandler_H
+
diff --git a/Sockets/Sockets-config.cpp b/Sockets/Sockets-config.cpp
new file mode 100644
index 0000000..7311147
--- /dev/null
+++ b/Sockets/Sockets-config.cpp
@@ -0,0 +1,121 @@
+/**
+ ** \file Sockets-config.cpp
+ ** \date 2006-09-04
+ ** \author grymse@alhem.net
+**/
+/*
+Copyright (C) 2007 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.
+*/
+#include <stdio.h>
+#include <string.h>
+#include "sockets-config.h"
+#include "socket_include.h"
+
+int main(int argc,char *argv[])
+{
+ if (argc > 1 && !strcmp(argv[1], "-info"))
+ {
+#ifdef HAVE_OPENSSL
+ printf("SSL support\n");
+#endif
+#ifdef IPPROTO_IPV6
+ printf("IPv6 support\n");
+#endif
+#ifdef USE_SCTP
+#ifdef IPPROTO_SCTP
+ printf("SCTP support\n");
+# ifdef HAVE_SCTP
+ printf(" HAVE_SCTP: yes\n");
+# else
+ printf(" HAVE_SCTP: no\n");
+# endif
+# ifdef HAVE_KERNEL_SCTP
+ printf(" HAVE_KERNEL_SCTP: yes\n");
+# else
+ printf(" HAVE_KERNEL_SCTP: no\n");
+# endif
+# ifdef HAVE_SCTP_PRSCTP
+ printf(" HAVE_SCTP_PRSCTP: yes\n");
+# else
+ printf(" HAVE_SCTP_PRSCTP: no\n");
+# endif
+# ifdef HAVE_SCTP_ADDIP
+ printf(" HAVE_SCTP_ADDIP: yes\n");
+# else
+ printf(" HAVE_SCTP_ADDIP: no\n");
+# endif
+# ifdef HAVE_SCTP_CANSET_PRIMARY
+ printf(" HAVE_SCTP_CANSETPRIMARY: yes\n");
+# else
+ printf(" HAVE_SCTP_CANSETPRIMARY: no\n");
+# endif
+# ifdef HAVE_SCTP_SAT_NETWORK_CAPABILITY
+ printf(" HAVE_SCTP_SAT_NETWORK_CAPABILITY: yes\n");
+# else
+ printf(" HAVE_SCTP_SAT_NETWORK_CAPABILITY: no\n");
+# endif
+# ifdef HAVE_SCTP_MULTIBUF
+ printf(" HAVE_SCTP_MULTIBUF: yes\n");
+# else
+ printf(" HAVE_SCTP_MULTIBUF: no\n");
+# endif
+# ifdef HAVE_SCTP_NOCONNECT
+ printf(" HAVE_SCTP_NOCONNECT: yes\n");
+# else
+ printf(" HAVE_SCTP_NOCONNECT: no\n");
+# endif
+# ifdef HAVE_SCTP_EXT_RCVINFO
+ printf(" HAVE_SCTP_EXT_RCVINFO: yes\n");
+# else
+ printf(" HAVE_SCTP_EXT_RCVINFO: no\n");
+# endif
+#else
+ printf("No SCTP support\n");
+#endif
+#endif
+ return 0;
+ }
+ printf(" -D_VERSION='\"%s\"'", _VERSION);
+
+#ifdef LINUX
+ printf(" -DLINUX");
+#endif
+#ifdef MACOSX
+ printf(" -DMACOSX");
+#endif
+#ifdef SOLARIS
+ printf(" -DSOLARIS");
+#endif
+#ifdef SOLARIS8
+ printf(" -DSOLARIS8");
+#endif
+#ifdef _WIN32
+ printf(" -D_WIN32");
+#endif
+#ifdef __CYGWIN__
+ printf(" -D__CYGWIN__");
+#endif
+#ifdef SOCKETS_NAMESPACE
+ printf(" -DSOCKETS_NAMESPACE=%s", SOCKETS_NAMESPACE_STR);
+#endif
+#ifdef _DEBUG
+ printf(" -D_DEBUG");
+#endif
+
+}
+
+
diff --git a/Sockets/StdLog.h b/Sockets/StdLog.h
new file mode 100644
index 0000000..c07037b
--- /dev/null
+++ b/Sockets/StdLog.h
@@ -0,0 +1,74 @@
+/** \file StdLog.h
+ ** \date 2004-06-01
+ ** \author grymse@alhem.net
+**/
+/*
+Copyright (C) 2004-2007 Anders Hedstrom
+
+This library is made available under the terms of the GNU GPL.
+
+If you would like to use this library in a closed-source application,
+a separate license agreement is available. For information about
+the closed-source license agreement for the C++ sockets library,
+please visit http://www.alhem.net/Sockets/license.html and/or
+email license@alhem.net.
+
+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.
+*/
+#ifndef _SOCKETS_StdLog_H
+#define _SOCKETS_StdLog_H
+
+#include "sockets-config.h"
+#include <string>
+
+#ifdef SOCKETS_NAMESPACE
+namespace SOCKETS_NAMESPACE {
+#endif
+
+/** error level enum. */
+typedef enum
+{
+ LOG_LEVEL_WARNING = 0,
+ LOG_LEVEL_ERROR,
+ LOG_LEVEL_FATAL,
+ LOG_LEVEL_INFO
+} loglevel_t;
+
+
+class ISocketHandler;
+class Socket;
+
+/** \defgroup logging Log help classes */
+/** Log class interface.
+ \ingroup logging */
+class StdLog
+{
+public:
+ virtual ~StdLog() {}
+
+ virtual void error(ISocketHandler *,Socket *,
+ const std::string& user_text,
+ int err,
+ const std::string& sys_err,
+ loglevel_t = LOG_LEVEL_WARNING) = 0;
+};
+
+
+#ifdef SOCKETS_NAMESPACE
+}
+#endif
+
+#endif // _SOCKETS_StdLog_H
+
diff --git a/Sockets/StdoutLog.cpp b/Sockets/StdoutLog.cpp
new file mode 100644
index 0000000..c01d8b8
--- /dev/null
+++ b/Sockets/StdoutLog.cpp
@@ -0,0 +1,96 @@
+/** \file StdoutLog.cpp
+ ** \date 2004-06-01
+ ** \author grymse@alhem.net
+**/
+/*
+Copyright (C) 2004-2007 Anders Hedstrom
+
+This library is made available under the terms of the GNU GPL.
+
+If you would like to use this library in a closed-source application,
+a separate license agreement is available. For information about
+the closed-source license agreement for the C++ sockets library,
+please visit http://www.alhem.net/Sockets/license.html and/or
+email license@alhem.net.
+
+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 _MSC_VER
+#pragma warning(disable:4786)
+#endif
+#include "ISocketHandler.h"
+#include "Socket.h"
+#include "StdoutLog.h"
+
+#ifdef SOCKETS_NAMESPACE
+namespace SOCKETS_NAMESPACE {
+#endif
+
+
+
+
+void StdoutLog::error(ISocketHandler *,Socket *sock,const std::string& call,int err,const std::string& sys_err,loglevel_t lvl)
+{
+ time_t t = time(NULL);
+ struct tm tp;
+#ifdef _WIN32
+ memcpy(&tp, localtime(&t), sizeof(tp));
+#else
+ localtime_r(&t, &tp);
+#endif
+ std::string level;
+
+ switch (lvl)
+ {
+ case LOG_LEVEL_WARNING:
+ level = "Warning";
+ break;
+ case LOG_LEVEL_ERROR:
+ level = "Error";
+ break;
+ case LOG_LEVEL_FATAL:
+ level = "Fatal";
+ break;
+ case LOG_LEVEL_INFO:
+ level = "Info";
+ break;
+ }
+ if (sock)
+ {
+ printf("%d-%02d-%02d %02d:%02d:%02d :: fd %d :: %s: %d %s (%s)\n",
+ tp.tm_year + 1900,
+ tp.tm_mon + 1,
+ tp.tm_mday,
+ tp.tm_hour,tp.tm_min,tp.tm_sec,
+ sock -> GetSocket(),
+ call.c_str(),err,sys_err.c_str(),level.c_str());
+ }
+ else
+ {
+ printf("%d-%02d-%02d %02d:%02d:%02d :: %s: %d %s (%s)\n",
+ tp.tm_year + 1900,
+ tp.tm_mon + 1,
+ tp.tm_mday,
+ tp.tm_hour,tp.tm_min,tp.tm_sec,
+ call.c_str(),err,sys_err.c_str(),level.c_str());
+ }
+}
+
+
+#ifdef SOCKETS_NAMESPACE
+}
+#endif
+
+
diff --git a/Sockets/StdoutLog.h b/Sockets/StdoutLog.h
new file mode 100644
index 0000000..5f96b34
--- /dev/null
+++ b/Sockets/StdoutLog.h
@@ -0,0 +1,57 @@
+/** \file StdoutLog.h
+ ** \date 2004-06-01
+ ** \author grymse@alhem.net
+**/
+/*
+Copyright (C) 2004-2007 Anders Hedstrom
+
+This library is made available under the terms of the GNU GPL.
+
+If you would like to use this library in a closed-source application,
+a separate license agreement is available. For information about
+the closed-source license agreement for the C++ sockets library,
+please visit http://www.alhem.net/Sockets/license.html and/or
+email license@alhem.net.
+
+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.
+*/
+#ifndef _SOCKETS_StdoutLog_H
+#define _SOCKETS_StdoutLog_H
+
+#include "sockets-config.h"
+#include "StdLog.h"
+
+#ifdef SOCKETS_NAMESPACE
+namespace SOCKETS_NAMESPACE {
+#endif
+
+
+/** StdLog implementation, logs to stdout.
+ \ingroup logging */
+class StdoutLog : public StdLog
+{
+public:
+ void error(ISocketHandler *,Socket *,const std::string& call,int err,const std::string& sys_err,loglevel_t);
+};
+
+
+
+
+#ifdef SOCKETS_NAMESPACE
+}
+#endif
+
+#endif // _SOCKETS_StdoutLog_H
+
diff --git a/Sockets/StreamSocket.cpp b/Sockets/StreamSocket.cpp
new file mode 100644
index 0000000..5c5780e
--- /dev/null
+++ b/Sockets/StreamSocket.cpp
@@ -0,0 +1,169 @@
+#include "StreamSocket.h"
+#include "ISocketHandler.h"
+
+
+#ifdef SOCKETS_NAMESPACE
+namespace SOCKETS_NAMESPACE {
+#endif
+
+
+StreamSocket::StreamSocket(ISocketHandler& h) : Socket(h)
+,m_bConnecting(false)
+,m_connect_timeout(5)
+,m_flush_before_close(true)
+,m_connection_retry(0)
+,m_retries(0)
+,m_call_on_connect(false)
+,m_b_retry_connect(false)
+,m_line_protocol(false)
+,m_shutdown(0)
+{
+}
+
+
+StreamSocket::~StreamSocket()
+{
+}
+
+
+void StreamSocket::SetConnecting(bool x)
+{
+ if (x != m_bConnecting)
+ {
+ m_bConnecting = x;
+ if (x)
+ {
+ SetTimeout( GetConnectTimeout() );
+ }
+ else
+ {
+ SetTimeout( 0 );
+ }
+ }
+}
+
+
+bool StreamSocket::Connecting()
+{
+ return m_bConnecting;
+}
+
+
+bool StreamSocket::Ready()
+{
+ if (GetSocket() != INVALID_SOCKET && !Connecting() && !CloseAndDelete())
+ return true;
+ return false;
+}
+
+
+void StreamSocket::SetConnectTimeout(int x)
+{
+ m_connect_timeout = x;
+}
+
+
+int StreamSocket::GetConnectTimeout()
+{
+ return m_connect_timeout;
+}
+
+
+void StreamSocket::SetFlushBeforeClose(bool x)
+{
+ m_flush_before_close = x;
+}
+
+
+bool StreamSocket::GetFlushBeforeClose()
+{
+ return m_flush_before_close;
+}
+
+
+int StreamSocket::GetConnectionRetry()
+{
+ return m_connection_retry;
+}
+
+
+void StreamSocket::SetConnectionRetry(int x)
+{
+ m_connection_retry = x;
+}
+
+
+int StreamSocket::GetConnectionRetries()
+{
+ return m_retries;
+}
+
+
+void StreamSocket::IncreaseConnectionRetries()
+{
+ m_retries++;
+}
+
+
+void StreamSocket::ResetConnectionRetries()
+{
+ m_retries = 0;
+}
+
+
+void StreamSocket::SetCallOnConnect(bool x)
+{
+ Handler().AddList(GetSocket(), LIST_CALLONCONNECT, x);
+ m_call_on_connect = x;
+}
+
+
+bool StreamSocket::CallOnConnect()
+{
+ return m_call_on_connect;
+}
+
+
+void StreamSocket::SetRetryClientConnect(bool x)
+{
+ Handler().AddList(GetSocket(), LIST_RETRY, x);
+ m_b_retry_connect = x;
+}
+
+
+bool StreamSocket::RetryClientConnect()
+{
+ return m_b_retry_connect;
+}
+
+
+void StreamSocket::SetLineProtocol(bool x)
+{
+ m_line_protocol = x;
+}
+
+
+bool StreamSocket::LineProtocol()
+{
+ return m_line_protocol;
+}
+
+
+void StreamSocket::SetShutdown(int x)
+{
+ m_shutdown = x;
+}
+
+
+int StreamSocket::GetShutdown()
+{
+ return m_shutdown;
+}
+
+
+
+
+#ifdef SOCKETS_NAMESPACE
+} // namespace SOCKETS_NAMESPACE {
+#endif
+
diff --git a/Sockets/StreamSocket.h b/Sockets/StreamSocket.h
new file mode 100644
index 0000000..3c24811
--- /dev/null
+++ b/Sockets/StreamSocket.h
@@ -0,0 +1,127 @@
+#ifndef _StreamSocket_H
+#define _StreamSocket_H
+
+#include "Socket.h"
+
+
+#ifdef SOCKETS_NAMESPACE
+namespace SOCKETS_NAMESPACE {
+#endif
+
+
+/** SOCK_STREAM Socket base class.
+ \ingroup basic */
+class StreamSocket : public Socket
+{
+public:
+ StreamSocket(ISocketHandler& );
+ ~StreamSocket();
+
+ /** Socket should Check Connect on next write event from select(). */
+ void SetConnecting(bool = true);
+
+ /** Check connecting flag.
+ \return true if the socket is still trying to connect */
+ bool Connecting();
+
+ /** Returns true when socket file descriptor is valid,
+ socket connection is established, and socket is not about to
+ be closed. */
+ bool Ready();
+
+ /** Set timeout to use for connection attempt.
+ \param x Timeout in seconds */
+ void SetConnectTimeout(int x);
+
+ /** Return number of seconds to wait for a connection.
+ \return Connection timeout (seconds) */
+ int GetConnectTimeout();
+
+ /** Set flush before close to make a tcp socket completely empty its
+ output buffer before closing the connection. */
+ void SetFlushBeforeClose(bool = true);
+
+ /** Check flush before status.
+ \return true if the socket should send all data before closing */
+ bool GetFlushBeforeClose();
+
+ /** Define number of connection retries (tcp only).
+ n = 0 - no retry
+ n > 0 - number of retries
+ n = -1 - unlimited retries */
+ void SetConnectionRetry(int n);
+
+ /** Get number of maximum connection retries (tcp only). */
+ int GetConnectionRetry();
+
+ /** Increase number of actual connection retries (tcp only). */
+ void IncreaseConnectionRetries();
+
+ /** Get number of actual connection retries (tcp only). */
+ int GetConnectionRetries();
+
+ /** Reset actual connection retries (tcp only). */
+ void ResetConnectionRetries();
+
+ // LIST_CALLONCONNECT
+
+ /** Instruct socket to call OnConnect callback next sockethandler cycle. */
+ void SetCallOnConnect(bool x = true);
+
+ /** Check call on connect flag.
+ \return true if OnConnect() should be called a.s.a.p */
+ bool CallOnConnect();
+
+ // LIST_RETRY
+
+ /** Set flag to initiate a connection attempt after a connection timeout. */
+ void SetRetryClientConnect(bool x = true);
+
+ /** Check if a connection attempt should be made.
+ \return true when another attempt should be made */
+ bool RetryClientConnect();
+
+ /** Called after OnRead if socket is in line protocol mode.
+ \sa SetLineProtocol */
+ /** Enable the OnLine callback. Do not create your own OnRead
+ * callback when using this. */
+ virtual void SetLineProtocol(bool = true);
+
+ /** Check line protocol mode.
+ \return true if socket is in line protocol mode */
+ bool LineProtocol();
+
+ /** Set shutdown status. */
+ void SetShutdown(int);
+
+ /** Get shutdown status. */
+ int GetShutdown();
+
+ /** Returns IPPROTO_TCP or IPPROTO_SCTP */
+ virtual int Protocol() = 0;
+
+protected:
+ StreamSocket(const StreamSocket& ) {} // copy constructor
+
+private:
+ StreamSocket& operator=(const StreamSocket& ) { return *this; } // assignment operator
+
+ bool m_bConnecting; ///< Flag indicating connection in progress
+ int m_connect_timeout; ///< Connection timeout (seconds)
+ bool m_flush_before_close; ///< Send all data before closing (default true)
+ int m_connection_retry; ///< Maximum connection retries (tcp)
+ int m_retries; ///< Actual number of connection retries (tcp)
+ bool m_call_on_connect; ///< OnConnect will be called next ISocketHandler cycle if true
+ bool m_b_retry_connect; ///< Try another connection attempt next ISocketHandler cycle
+ bool m_line_protocol; ///< Line protocol mode flag
+ int m_shutdown; ///< Shutdown status
+};
+
+
+#ifdef SOCKETS_NAMESPACE
+} // namespace SOCKETS_NAMESPACE {
+#endif
+
+
+#endif // _StreamSocket_H
+
diff --git a/Sockets/TcpSocket.cpp b/Sockets/TcpSocket.cpp
new file mode 100644
index 0000000..960ac35
--- /dev/null
+++ b/Sockets/TcpSocket.cpp
@@ -0,0 +1,1729 @@
+/** \file TcpSocket.cpp
+ ** \date 2004-02-13
+ ** \author grymse@alhem.net
+**/
+/*
+Copyright (C) 2004-2007 Anders Hedstrom
+
+This library is made available under the terms of the GNU GPL.
+
+If you would like to use this library in a closed-source application,
+a separate license agreement is available. For information about
+the closed-source license agreement for the C++ sockets library,
+please visit http://www.alhem.net/Sockets/license.html and/or
+email license@alhem.net.
+
+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
+#ifdef _MSC_VER
+#pragma warning(disable:4786)
+#endif
+#include <stdlib.h>
+#else
+#include <errno.h>
+#endif
+#include "ISocketHandler.h"
+#include <fcntl.h>
+#include <assert.h>
+#include <stdarg.h>
+#ifdef HAVE_OPENSSL
+#include <openssl/rand.h>
+#include <openssl/err.h>
+#endif
+
+#include "TcpSocket.h"
+#include "Utility.h"
+#include "Ipv4Address.h"
+#include "Ipv6Address.h"
+#include "Mutex.h"
+#include "IFile.h"
+
+#ifdef SOCKETS_NAMESPACE
+namespace SOCKETS_NAMESPACE {
+#endif
+
+
+#ifdef _DEBUG
+#define DEB(x) x
+#else
+#define DEB(x)
+#endif
+
+
+// statics
+#ifdef HAVE_OPENSSL
+SSLInitializer TcpSocket::m_ssl_init;
+#endif
+
+
+// thanks, q
+#ifdef _MSC_VER
+#pragma warning(disable:4355)
+#endif
+TcpSocket::TcpSocket(ISocketHandler& h) : StreamSocket(h)
+,ibuf(TCP_BUFSIZE_READ)
+,m_b_input_buffer_disabled(false)
+,m_bytes_sent(0)
+,m_bytes_received(0)
+,m_skip_c(false)
+#ifdef SOCKETS_DYNAMIC_TEMP
+,m_buf(new char[TCP_BUFSIZE_READ + 1])
+#endif
+,m_obuf_top(NULL)
+,m_transfer_limit(0)
+,m_output_length(0)
+#ifdef HAVE_OPENSSL
+,m_ssl_ctx(NULL)
+,m_ssl(NULL)
+,m_sbio(NULL)
+#endif
+#ifdef ENABLE_SOCKS4
+,m_socks4_state(0)
+#endif
+#ifdef ENABLE_RESOLVER
+,m_resolver_id(0)
+#endif
+#ifdef ENABLE_RECONNECT
+,m_b_reconnect(false)
+,m_b_is_reconnect(false)
+#endif
+{
+}
+#ifdef _MSC_VER
+#pragma warning(default:4355)
+#endif
+
+
+#ifdef _MSC_VER
+#pragma warning(disable:4355)
+#endif
+TcpSocket::TcpSocket(ISocketHandler& h,size_t isize,size_t osize) : StreamSocket(h)
+,ibuf(isize)
+,m_b_input_buffer_disabled(false)
+,m_bytes_sent(0)
+,m_bytes_received(0)
+,m_skip_c(false)
+#ifdef SOCKETS_DYNAMIC_TEMP
+,m_buf(new char[TCP_BUFSIZE_READ + 1])
+#endif
+,m_obuf_top(NULL)
+,m_transfer_limit(0)
+,m_output_length(0)
+#ifdef HAVE_OPENSSL
+,m_ssl_ctx(NULL)
+,m_ssl(NULL)
+,m_sbio(NULL)
+#endif
+#ifdef ENABLE_SOCKS4
+,m_socks4_state(0)
+#endif
+#ifdef ENABLE_RESOLVER
+,m_resolver_id(0)
+#endif
+#ifdef ENABLE_RECONNECT
+,m_b_reconnect(false)
+,m_b_is_reconnect(false)
+#endif
+{
+}
+#ifdef _MSC_VER
+#pragma warning(default:4355)
+#endif
+
+
+TcpSocket::~TcpSocket()
+{
+#ifdef SOCKETS_DYNAMIC_TEMP
+ delete[] m_buf;
+#endif
+ // %! empty m_obuf
+#ifdef HAVE_OPENSSL
+ if (m_ssl)
+ {
+ SSL_free(m_ssl);
+ }
+#endif
+}
+
+
+bool TcpSocket::Open(ipaddr_t ip,port_t port,bool skip_socks)
+{
+ Ipv4Address ad(ip, port);
+ Ipv4Address local;
+ return Open(ad, local, skip_socks);
+}
+
+
+#ifdef ENABLE_IPV6
+#ifdef IPPROTO_IPV6
+bool TcpSocket::Open(in6_addr ip,port_t port,bool skip_socks)
+{
+ Ipv6Address ad(ip, port);
+ return Open(ad, skip_socks);
+}
+#endif
+#endif
+
+
+bool TcpSocket::Open(SocketAddress& ad,bool skip_socks)
+{
+ Ipv4Address bind_ad("0.0.0.0", 0);
+ return Open(ad, bind_ad, skip_socks);
+}
+
+
+bool TcpSocket::Open(SocketAddress& ad,SocketAddress& bind_ad,bool skip_socks)
+{
+ if (!ad.IsValid())
+ {
+ Handler().LogError(this, "Open", 0, "Invalid SocketAddress", LOG_LEVEL_FATAL);
+ SetCloseAndDelete();
+ return false;
+ }
+ if (Handler().GetCount() >= FD_SETSIZE)
+ {
+ Handler().LogError(this, "Open", 0, "no space left in fd_set", LOG_LEVEL_FATAL);
+ SetCloseAndDelete();
+ return false;
+ }
+ SetConnecting(false);
+#ifdef ENABLE_SOCKS4
+ SetSocks4(false);
+#endif
+ // check for pooling
+#ifdef ENABLE_POOL
+ if (Handler().PoolEnabled())
+ {
+ ISocketHandler::PoolSocket *pools = Handler().FindConnection(SOCK_STREAM, "tcp", ad);
+ if (pools)
+ {
+ CopyConnection( pools );
+ delete pools;
+
+ SetIsClient();
+ SetCallOnConnect(); // ISocketHandler must call OnConnect
+ Handler().LogError(this, "SetCallOnConnect", 0, "Found pooled connection", LOG_LEVEL_INFO);
+ return true;
+ }
+ }
+#endif
+ // if not, create new connection
+ SOCKET s = CreateSocket(ad.GetFamily(), SOCK_STREAM, "tcp");
+ if (s == INVALID_SOCKET)
+ {
+ return false;
+ }
+ // socket must be nonblocking for async connect
+ if (!SetNonblocking(true, s))
+ {
+ SetCloseAndDelete();
+ closesocket(s);
+ return false;
+ }
+#ifdef ENABLE_POOL
+ SetIsClient(); // client because we connect
+#endif
+ SetClientRemoteAddress(ad);
+ int n = 0;
+ if (bind_ad.GetPort() != 0)
+ {
+ bind(s, bind_ad, bind_ad);
+ }
+#ifdef ENABLE_SOCKS4
+ if (!skip_socks && GetSocks4Host() && GetSocks4Port())
+ {
+ Ipv4Address sa(GetSocks4Host(), GetSocks4Port());
+ {
+ std::string sockshost;
+ Utility::l2ip(GetSocks4Host(), sockshost);
+ Handler().LogError(this, "Open", 0, "Connecting to socks4 server @ " + sockshost + ":" +
+ Utility::l2string(GetSocks4Port()), LOG_LEVEL_INFO);
+ }
+ SetSocks4();
+ n = connect(s, sa, sa);
+ SetRemoteAddress(sa);
+ }
+ else
+#endif
+ {
+ n = connect(s, ad, ad);
+ SetRemoteAddress(ad);
+ }
+ if (n == -1)
+ {
+ // check error code that means a connect is in progress
+#ifdef _WIN32
+ if (Errno == WSAEWOULDBLOCK)
+#else
+ if (Errno == EINPROGRESS)
+#endif
+ {
+ Attach(s);
+ SetConnecting( true ); // this flag will control fd_set's
+ }
+ else
+#ifdef ENABLE_SOCKS4
+ if (Socks4() && Handler().Socks4TryDirect() ) // retry
+ {
+ closesocket(s);
+ return Open(ad, true);
+ }
+ else
+#endif
+#ifdef ENABLE_RECONNECT
+ if (Reconnect())
+ {
+ Handler().LogError(this, "connect: failed, reconnect pending", Errno, StrError(Errno), LOG_LEVEL_INFO);
+ Attach(s);
+ SetConnecting( true ); // this flag will control fd_set's
+ }
+ else
+#endif
+ {
+ Handler().LogError(this, "connect: failed", Errno, StrError(Errno), LOG_LEVEL_FATAL);
+ SetCloseAndDelete();
+ closesocket(s);
+ return false;
+ }
+ }
+ else
+ {
+ Attach(s);
+ SetCallOnConnect(); // ISocketHandler must call OnConnect
+ }
+
+ // 'true' means connected or connecting(not yet connected)
+ // 'false' means something failed
+ return true; //!Connecting();
+}
+
+
+bool TcpSocket::Open(const std::string &host,port_t port)
+{
+#ifdef ENABLE_IPV6
+#ifdef IPPROTO_IPV6
+ if (IsIpv6())
+ {
+#ifdef ENABLE_RESOLVER
+ if (!Handler().ResolverEnabled() || Utility::isipv6(host) )
+ {
+#endif
+ in6_addr a;
+ if (!Utility::u2ip(host, a))
+ {
+ SetCloseAndDelete();
+ return false;
+ }
+ Ipv6Address ad(a, port);
+ Ipv6Address local;
+ return Open(ad, local);
+#ifdef ENABLE_RESOLVER
+ }
+ m_resolver_id = Resolve6(host, port);
+ return true;
+#endif
+ }
+#endif
+#endif
+#ifdef ENABLE_RESOLVER
+ if (!Handler().ResolverEnabled() || Utility::isipv4(host) )
+ {
+#endif
+ ipaddr_t l;
+ if (!Utility::u2ip(host,l))
+ {
+ SetCloseAndDelete();
+ return false;
+ }
+ Ipv4Address ad(l, port);
+ Ipv4Address local;
+ return Open(ad, local);
+#ifdef ENABLE_RESOLVER
+ }
+ // resolve using async resolver thread
+ m_resolver_id = Resolve(host, port);
+ return true;
+#endif
+}
+
+
+#ifdef ENABLE_RESOLVER
+void TcpSocket::OnResolved(int id,ipaddr_t a,port_t port)
+{
+DEB( fprintf(stderr, "TcpSocket::OnResolved id %d addr %x port %d\n", id, a, port);)
+ if (id == m_resolver_id)
+ {
+ if (a && port)
+ {
+ Ipv4Address ad(a, port);
+ Ipv4Address local;
+ if (Open(ad, local))
+ {
+ if (!Handler().Valid(this))
+ {
+ Handler().Add(this);
+ }
+ }
+ }
+ else
+ {
+ Handler().LogError(this, "OnResolved", 0, "Resolver failed", LOG_LEVEL_FATAL);
+ SetCloseAndDelete();
+ }
+ }
+ else
+ {
+ Handler().LogError(this, "OnResolved", id, "Resolver returned wrong job id", LOG_LEVEL_FATAL);
+ SetCloseAndDelete();
+ }
+}
+
+
+#ifdef ENABLE_IPV6
+void TcpSocket::OnResolved(int id,in6_addr& a,port_t port)
+{
+ if (id == m_resolver_id)
+ {
+ Ipv6Address ad(a, port);
+ if (ad.IsValid())
+ {
+ Ipv6Address local;
+ if (Open(ad, local))
+ {
+ if (!Handler().Valid(this))
+ {
+ Handler().Add(this);
+ }
+ }
+ }
+ }
+ else
+ {
+ Handler().LogError(this, "OnResolved", id, "Resolver returned wrong job id", LOG_LEVEL_FATAL);
+ SetCloseAndDelete();
+ }
+}
+#endif
+#endif
+
+
+void TcpSocket::OnRead()
+{
+ int n = 0;
+#ifdef SOCKETS_DYNAMIC_TEMP
+ char *buf = m_buf;
+#else
+ char buf[TCP_BUFSIZE_READ];
+#endif
+#ifdef HAVE_OPENSSL
+ if (IsSSL())
+ {
+ if (!Ready())
+ return;
+ n = SSL_read(m_ssl, buf, TCP_BUFSIZE_READ);
+ if (n == -1)
+ {
+ n = SSL_get_error(m_ssl, n);
+ switch (n)
+ {
+ case SSL_ERROR_NONE:
+ case SSL_ERROR_WANT_READ:
+ case SSL_ERROR_WANT_WRITE:
+ break;
+ case SSL_ERROR_ZERO_RETURN:
+DEB( fprintf(stderr, "SSL_read() returns zero - closing socket\n");)
+ OnDisconnect();
+ SetCloseAndDelete(true);
+ SetFlushBeforeClose(false);
+#ifdef ENABLE_POOL
+ SetLost();
+#endif
+ break;
+ default:
+DEB( fprintf(stderr, "SSL read problem, errcode = %d\n",n);)
+ OnDisconnect();
+ SetCloseAndDelete(true);
+ SetFlushBeforeClose(false);
+#ifdef ENABLE_POOL
+ SetLost();
+#endif
+ }
+ return;
+ }
+ else
+ if (!n)
+ {
+ OnDisconnect();
+ SetCloseAndDelete(true);
+ SetFlushBeforeClose(false);
+#ifdef ENABLE_POOL
+ SetLost();
+#endif
+ SetShutdown(SHUT_WR);
+ return;
+ }
+ else
+ if (n > 0 && n <= TCP_BUFSIZE_READ)
+ {
+ m_bytes_received += n;
+ if (GetTrafficMonitor())
+ {
+ GetTrafficMonitor() -> fwrite(buf, 1, n);
+ }
+ if (!m_b_input_buffer_disabled && !ibuf.Write(buf,n))
+ {
+ Handler().LogError(this, "OnRead(ssl)", 0, "ibuf overflow", LOG_LEVEL_WARNING);
+ }
+ }
+ else
+ {
+ Handler().LogError(this, "OnRead(ssl)", n, "abnormal value from SSL_read", LOG_LEVEL_ERROR);
+ }
+ }
+ else
+#endif // HAVE_OPENSSL
+ {
+ n = recv(GetSocket(), buf, TCP_BUFSIZE_READ, MSG_NOSIGNAL);
+ if (n == -1)
+ {
+ Handler().LogError(this, "read", Errno, StrError(Errno), LOG_LEVEL_FATAL);
+ OnDisconnect();
+ SetCloseAndDelete(true);
+ SetFlushBeforeClose(false);
+#ifdef ENABLE_POOL
+ SetLost();
+#endif
+ return;
+ }
+ else
+ if (!n)
+ {
+ OnDisconnect();
+ SetCloseAndDelete(true);
+ SetFlushBeforeClose(false);
+#ifdef ENABLE_POOL
+ SetLost();
+#endif
+ SetShutdown(SHUT_WR);
+ return;
+ }
+ else
+ if (n > 0 && n <= TCP_BUFSIZE_READ)
+ {
+ m_bytes_received += n;
+ if (GetTrafficMonitor())
+ {
+ GetTrafficMonitor() -> fwrite(buf, 1, n);
+ }
+ if (!m_b_input_buffer_disabled && !ibuf.Write(buf,n))
+ {
+ Handler().LogError(this, "OnRead", 0, "ibuf overflow", LOG_LEVEL_WARNING);
+ }
+ }
+ else
+ {
+ Handler().LogError(this, "OnRead", n, "abnormal value from recv", LOG_LEVEL_ERROR);
+ }
+ }
+ //
+ OnRead( buf, n );
+}
+
+
+void TcpSocket::OnRead( char *buf, size_t n )
+{
+ // unbuffered
+ if (n > 0 && n <= TCP_BUFSIZE_READ)
+ {
+ if (LineProtocol())
+ {
+ buf[n] = 0;
+ size_t i = 0;
+ if (m_skip_c && (buf[i] == 13 || buf[i] == 10) && buf[i] != m_c)
+ {
+ m_skip_c = false;
+ i++;
+ }
+ size_t x = i;
+ for (; i < n && LineProtocol(); i++)
+ {
+ while ((buf[i] == 13 || buf[i] == 10) && LineProtocol())
+ {
+ char c = buf[i];
+ buf[i] = 0;
+ if (buf[x])
+ {
+ m_line += (buf + x);
+ }
+ OnLine( m_line );
+ i++;
+ m_skip_c = true;
+ m_c = c;
+ if (i < n && (buf[i] == 13 || buf[i] == 10) && buf[i] != c)
+ {
+ m_skip_c = false;
+ i++;
+ }
+ x = i;
+ m_line = "";
+ }
+ if (!LineProtocol())
+ {
+ break;
+ }
+ }
+ if (!LineProtocol())
+ {
+ if (i < n)
+ {
+ OnRawData(buf + i, n - i);
+ }
+ }
+ else
+ if (buf[x])
+ {
+ m_line += (buf + x);
+ }
+ }
+ else
+ {
+ OnRawData(buf, n);
+ }
+ }
+ if (m_b_input_buffer_disabled)
+ {
+ return;
+ }
+ // further processing: socks4
+#ifdef ENABLE_SOCKS4
+ if (Socks4())
+ {
+ bool need_more = false;
+ while (GetInputLength() && !need_more && !CloseAndDelete())
+ {
+ need_more = OnSocks4Read();
+ }
+ }
+#endif
+}
+
+
+void TcpSocket::OnWriteComplete()
+{
+}
+
+
+void TcpSocket::OnWrite()
+{
+ if (Connecting())
+ {
+ int err = SoError();
+
+ // don't reset connecting flag on error here, we want the OnConnectFailed timeout later on
+ if (!err) // ok
+ {
+ Set(!IsDisableRead(), false);
+ SetConnecting(false);
+ SetCallOnConnect();
+ return;
+ }
+ Handler().LogError(this, "tcp: connect failed", err, StrError(err), LOG_LEVEL_FATAL);
+ Set(false, false); // no more monitoring because connection failed
+
+ // failed
+#ifdef ENABLE_SOCKS4
+ if (Socks4())
+ {
+ // %! leave 'Connecting' flag set?
+ OnSocks4ConnectFailed();
+ return;
+ }
+#endif
+ if (GetConnectionRetry() == -1 ||
+ (GetConnectionRetry() && GetConnectionRetries() < GetConnectionRetry()) )
+ {
+ // even though the connection failed at once, only retry after
+ // the connection timeout.
+ // should we even try to connect again, when CheckConnect returns
+ // false it's because of a connection error - not a timeout...
+ return;
+ }
+ SetConnecting(false);
+ SetCloseAndDelete( true );
+ /// \todo state reason why connect failed
+ OnConnectFailed();
+ return;
+ }
+ // try send next block in buffer
+ // if full block is sent, repeat
+ // if all blocks are sent, reset m_wfds
+
+ bool repeat = false;
+ size_t sz = m_transfer_limit ? GetOutputLength() : 0;
+ do
+ {
+ output_l::iterator it = m_obuf.begin();
+ OUTPUT *p = *it;
+ repeat = false;
+ int n = TryWrite(p -> Buf(), p -> Len());
+ if (n > 0)
+ {
+ size_t left = p -> Remove(n);
+ m_output_length -= n;
+ if (!left)
+ {
+ delete p;
+ m_obuf.erase(it);
+ if (!m_obuf.size())
+ {
+ m_obuf_top = NULL;
+ OnWriteComplete();
+ }
+ else
+ {
+ repeat = true;
+ }
+ }
+ }
+ } while (repeat);
+
+ if (m_transfer_limit && sz > m_transfer_limit && GetOutputLength() < m_transfer_limit)
+ {
+ OnTransferLimit();
+ }
+
+ // check output buffer set, set/reset m_wfds accordingly
+ {
+ bool br;
+ bool bw;
+ bool bx;
+ Handler().Get(GetSocket(), br, bw, bx);
+ if (m_obuf.size())
+ Set(br, true);
+ else
+ Set(br, false);
+ }
+}
+
+
+int TcpSocket::TryWrite(const char *buf, size_t len)
+{
+ int n = 0;
+#ifdef HAVE_OPENSSL
+ if (IsSSL())
+ {
+ n = SSL_write(m_ssl, buf, (int)len);
+ if (n == -1)
+ {
+ int errnr = SSL_get_error(m_ssl, n);
+ if ( errnr != SSL_ERROR_WANT_READ && errnr != SSL_ERROR_WANT_WRITE )
+ {
+ OnDisconnect();
+ SetCloseAndDelete(true);
+ SetFlushBeforeClose(false);
+#ifdef ENABLE_POOL
+ SetLost();
+#endif
+ const char *errbuf = ERR_error_string(errnr, NULL);
+ Handler().LogError(this, "OnWrite/SSL_write", errnr, errbuf, LOG_LEVEL_FATAL);
+ }
+ return 0;
+ }
+ else
+ if (!n)
+ {
+ OnDisconnect();
+ SetCloseAndDelete(true);
+ SetFlushBeforeClose(false);
+#ifdef ENABLE_POOL
+ SetLost();
+#endif
+DEB( int errnr = SSL_get_error(m_ssl, n);
+ const char *errbuf = ERR_error_string(errnr, NULL);
+ fprintf(stderr, "SSL_write() returns 0: %d : %s\n",errnr, errbuf);)
+ }
+ }
+ else
+#endif // HAVE_OPENSSL
+ {
+ n = send(GetSocket(), buf, (int)len, MSG_NOSIGNAL);
+ if (n == -1)
+ {
+ // normal error codes:
+ // WSAEWOULDBLOCK
+ // EAGAIN or EWOULDBLOCK
+#ifdef _WIN32
+ if (Errno != WSAEWOULDBLOCK)
+#else
+ if (Errno != EWOULDBLOCK)
+#endif
+ {
+ Handler().LogError(this, "send", Errno, StrError(Errno), LOG_LEVEL_FATAL);
+ OnDisconnect();
+ SetCloseAndDelete(true);
+ SetFlushBeforeClose(false);
+#ifdef ENABLE_POOL
+ SetLost();
+#endif
+ }
+ return 0;
+ }
+ }
+ if (n > 0)
+ {
+ m_bytes_sent += n;
+ if (GetTrafficMonitor())
+ {
+ GetTrafficMonitor() -> fwrite(buf, 1, n);
+ }
+ }
+ return n;
+}
+
+
+void TcpSocket::Buffer(const char *buf, size_t len)
+{
+ size_t ptr = 0;
+ m_output_length += len;
+ while (ptr < len)
+ {
+ // buf/len => pbuf/sz
+ size_t space = 0;
+ if (m_obuf_top && (space = m_obuf_top -> Space()) > 0)
+ {
+ const char *pbuf = buf + ptr;
+ size_t sz = len - ptr;
+ if (space >= sz)
+ {
+ m_obuf_top -> Add(pbuf, sz);
+ ptr += sz;
+ }
+ else
+ {
+ m_obuf_top -> Add(pbuf, space);
+ ptr += space;
+ }
+ }
+ else
+ {
+ m_obuf_top = new OUTPUT;
+ m_obuf.push_back( m_obuf_top );
+ }
+ }
+}
+
+
+void TcpSocket::Send(const std::string &str,int i)
+{
+ SendBuf(str.c_str(),str.size(),i);
+}
+
+
+void TcpSocket::SendBuf(const char *buf,size_t len,int)
+{
+ if (!Ready() && !Connecting())
+ {
+ Handler().LogError(this, "SendBuf", -1, "Attempt to write to a non-ready socket" ); // warning
+ if (GetSocket() == INVALID_SOCKET)
+ Handler().LogError(this, "SendBuf", 0, " * GetSocket() == INVALID_SOCKET", LOG_LEVEL_INFO);
+ if (Connecting())
+ Handler().LogError(this, "SendBuf", 0, " * Connecting()", LOG_LEVEL_INFO);
+ if (CloseAndDelete())
+ Handler().LogError(this, "SendBuf", 0, " * CloseAndDelete()", LOG_LEVEL_INFO);
+ return;
+ }
+ if (!IsConnected())
+ {
+ Handler().LogError(this, "SendBuf", -1, "Attempt to write to a non-connected socket, will be sent on connect" ); // warning
+ Buffer(buf, len);
+ return;
+ }
+ if (m_obuf_top)
+ {
+ Buffer(buf, len);
+ return;
+ }
+ int n = TryWrite(buf, len);
+ if (n >= 0 && n < (int)len)
+ {
+ Buffer(buf + n, len - n);
+ }
+ // if ( data in buffer || !IsConnected )
+ // {
+ // add to buffer
+ // }
+ // else
+ // try_send
+ // if any data is unsent, buffer it and set m_wfds
+
+ // check output buffer set, set/reset m_wfds accordingly
+ {
+ bool br;
+ bool bw;
+ bool bx;
+ Handler().Get(GetSocket(), br, bw, bx);
+ if (m_obuf.size())
+ Set(br, true);
+ else
+ Set(br, false);
+ }
+}
+
+
+void TcpSocket::OnLine(const std::string& )
+{
+}
+
+
+#ifdef _MSC_VER
+#pragma warning(disable:4355)
+#endif
+TcpSocket::TcpSocket(const TcpSocket& s)
+:StreamSocket(s)
+,ibuf(0)
+{
+}
+#ifdef _MSC_VER
+#pragma warning(default:4355)
+#endif
+
+
+#ifdef ENABLE_SOCKS4
+void TcpSocket::OnSocks4Connect()
+{
+ char request[1000];
+ memset(request, 0, sizeof(request));
+ request[0] = 4; // socks v4
+ request[1] = 1; // command code: CONNECT
+ {
+ std::auto_ptr<SocketAddress> ad = GetClientRemoteAddress();
+ if (ad.get())
+ {
+ struct sockaddr *p0 = (struct sockaddr *)*ad;
+ struct sockaddr_in *p = (struct sockaddr_in *)p0;
+ if (p -> sin_family == AF_INET)
+ {
+ memcpy(request + 2, &p -> sin_port, 2); // nwbo is ok here
+ memcpy(request + 4, &p -> sin_addr, sizeof(struct in_addr));
+ }
+ else
+ {
+ /// \todo warn
+ }
+ }
+ else
+ {
+ /// \todo warn
+ }
+ }
+ strcpy(request + 8, GetSocks4Userid().c_str());
+ size_t length = GetSocks4Userid().size() + 8 + 1;
+ SendBuf(request, length);
+ m_socks4_state = 0;
+}
+
+
+void TcpSocket::OnSocks4ConnectFailed()
+{
+ Handler().LogError(this,"OnSocks4ConnectFailed",0,"connection to socks4 server failed, trying direct connection",LOG_LEVEL_WARNING);
+ if (!Handler().Socks4TryDirect())
+ {
+ SetConnecting(false);
+ SetCloseAndDelete();
+ OnConnectFailed(); // just in case
+ }
+ else
+ {
+ SetRetryClientConnect();
+ }
+}
+
+
+bool TcpSocket::OnSocks4Read()
+{
+ switch (m_socks4_state)
+ {
+ case 0:
+ ibuf.Read(&m_socks4_vn, 1);
+ m_socks4_state = 1;
+ break;
+ case 1:
+ ibuf.Read(&m_socks4_cd, 1);
+ m_socks4_state = 2;
+ break;
+ case 2:
+ if (GetInputLength() > 1)
+ {
+ ibuf.Read( (char *)&m_socks4_dstport, 2);
+ m_socks4_state = 3;
+ }
+ else
+ {
+ return true;
+ }
+ break;
+ case 3:
+ if (GetInputLength() > 3)
+ {
+ ibuf.Read( (char *)&m_socks4_dstip, 4);
+ SetSocks4(false);
+
+ switch (m_socks4_cd)
+ {
+ case 90:
+ OnConnect();
+ Handler().LogError(this, "OnSocks4Read", 0, "Connection established", LOG_LEVEL_INFO);
+ break;
+ case 91:
+ case 92:
+ case 93:
+ Handler().LogError(this,"OnSocks4Read",m_socks4_cd,"socks4 server reports connect failed",LOG_LEVEL_FATAL);
+ SetConnecting(false);
+ SetCloseAndDelete();
+ OnConnectFailed();
+ break;
+ default:
+ Handler().LogError(this,"OnSocks4Read",m_socks4_cd,"socks4 server unrecognized response",LOG_LEVEL_FATAL);
+ SetCloseAndDelete();
+ break;
+ }
+ }
+ else
+ {
+ return true;
+ }
+ break;
+ }
+ return false;
+}
+#endif
+
+
+void TcpSocket::Sendf(const char *format, ...)
+{
+ va_list ap;
+ va_start(ap, format);
+ char slask[5000]; // vsprintf / vsnprintf temporary
+#ifdef _WIN32
+ vsprintf(slask, format, ap);
+#else
+ vsnprintf(slask, 5000, format, ap);
+#endif
+ va_end(ap);
+ Send( slask );
+}
+
+
+#ifdef HAVE_OPENSSL
+void TcpSocket::OnSSLConnect()
+{
+ SetNonblocking(true);
+ {
+ if (m_ssl_ctx)
+ {
+DEB( fprintf(stderr, "SSL Context already initialized - closing socket\n");)
+ SetCloseAndDelete(true);
+ return;
+ }
+ InitSSLClient();
+ }
+ if (m_ssl_ctx)
+ {
+ /* Connect the SSL socket */
+ m_ssl = SSL_new(m_ssl_ctx);
+ if (!m_ssl)
+ {
+DEB( fprintf(stderr, " m_ssl is NULL\n");)
+ SetCloseAndDelete(true);
+ return;
+ }
+ SSL_set_mode(m_ssl, SSL_MODE_AUTO_RETRY);
+ m_sbio = BIO_new_socket((int)GetSocket(), BIO_NOCLOSE);
+ if (!m_sbio)
+ {
+DEB( fprintf(stderr, " m_sbio is NULL\n");)
+ SetCloseAndDelete(true);
+ return;
+ }
+ SSL_set_bio(m_ssl, m_sbio, m_sbio);
+ if (!SSLNegotiate())
+ {
+ SetSSLNegotiate();
+ }
+ }
+ else
+ {
+ SetCloseAndDelete();
+ }
+}
+
+
+void TcpSocket::OnSSLAccept()
+{
+ SetNonblocking(true);
+ {
+ if (m_ssl_ctx)
+ {
+DEB( fprintf(stderr, "SSL Context already initialized - closing socket\n");)
+ SetCloseAndDelete(true);
+ return;
+ }
+ InitSSLServer();
+ SetSSLServer();
+ }
+ if (m_ssl_ctx)
+ {
+ m_ssl = SSL_new(m_ssl_ctx);
+ if (!m_ssl)
+ {
+DEB( fprintf(stderr, " m_ssl is NULL\n");)
+ SetCloseAndDelete(true);
+ return;
+ }
+ SSL_set_mode(m_ssl, SSL_MODE_AUTO_RETRY);
+ m_sbio = BIO_new_socket((int)GetSocket(), BIO_NOCLOSE);
+ if (!m_sbio)
+ {
+DEB( fprintf(stderr, " m_sbio is NULL\n");)
+ SetCloseAndDelete(true);
+ return;
+ }
+ SSL_set_bio(m_ssl, m_sbio, m_sbio);
+// if (!SSLNegotiate())
+ {
+ SetSSLNegotiate();
+ }
+ }
+}
+
+
+bool TcpSocket::SSLNegotiate()
+{
+ if (!IsSSLServer()) // client
+ {
+ int r = SSL_connect(m_ssl);
+ if (r > 0)
+ {
+ SetSSLNegotiate(false);
+ /// \todo: resurrect certificate check... client
+// CheckCertificateChain( "");//ServerHOST);
+ SetNonblocking(false);
+ //
+ {
+ SetConnected();
+ if (GetOutputLength())
+ {
+ OnWrite();
+ }
+ }
+#ifdef ENABLE_RECONNECT
+ if (IsReconnect())
+ OnReconnect();
+ else
+#endif
+ {
+ OnConnect();
+ }
+ Handler().LogError(this, "SSLNegotiate/SSL_connect", 0, "Connection established", LOG_LEVEL_INFO);
+ return true;
+ }
+ else
+ if (!r)
+ {
+ Handler().LogError(this, "SSLNegotiate/SSL_connect", 0, "Connection failed", LOG_LEVEL_INFO);
+ SetSSLNegotiate(false);
+ SetCloseAndDelete();
+ OnSSLConnectFailed();
+ }
+ else
+ {
+ r = SSL_get_error(m_ssl, r);
+ if (r != SSL_ERROR_WANT_READ && r != SSL_ERROR_WANT_WRITE)
+ {
+ Handler().LogError(this, "SSLNegotiate/SSL_connect", -1, "Connection failed", LOG_LEVEL_INFO);
+DEB( fprintf(stderr, "SSL_connect() failed - closing socket, return code: %d\n",r);)
+ SetSSLNegotiate(false);
+ SetCloseAndDelete(true);
+ OnSSLConnectFailed();
+ }
+ }
+ }
+ else // server
+ {
+ int r = SSL_accept(m_ssl);
+ if (r > 0)
+ {
+ SetSSLNegotiate(false);
+ /// \todo: resurrect certificate check... server
+// CheckCertificateChain( "");//ClientHOST);
+ SetNonblocking(false);
+ //
+ {
+ SetConnected();
+ if (GetOutputLength())
+ {
+ OnWrite();
+ }
+ }
+ OnAccept();
+ Handler().LogError(this, "SSLNegotiate/SSL_accept", 0, "Connection established", LOG_LEVEL_INFO);
+ return true;
+ }
+ else
+ if (!r)
+ {
+ Handler().LogError(this, "SSLNegotiate/SSL_accept", 0, "Connection failed", LOG_LEVEL_INFO);
+ SetSSLNegotiate(false);
+ SetCloseAndDelete();
+ OnSSLAcceptFailed();
+ }
+ else
+ {
+ r = SSL_get_error(m_ssl, r);
+ if (r != SSL_ERROR_WANT_READ && r != SSL_ERROR_WANT_WRITE)
+ {
+ Handler().LogError(this, "SSLNegotiate/SSL_accept", -1, "Connection failed", LOG_LEVEL_INFO);
+DEB( fprintf(stderr, "SSL_accept() failed - closing socket, return code: %d\n",r);)
+ SetSSLNegotiate(false);
+ SetCloseAndDelete(true);
+ OnSSLAcceptFailed();
+ }
+ }
+ }
+ return false;
+}
+
+
+void TcpSocket::InitSSLClient()
+{
+ InitializeContext("", SSLv23_method());
+}
+
+
+void TcpSocket::InitSSLServer()
+{
+ Handler().LogError(this, "InitSSLServer", 0, "You MUST implement your own InitSSLServer method", LOG_LEVEL_FATAL);
+ SetCloseAndDelete();
+}
+
+
+void TcpSocket::InitializeContext(const std::string& context, SSL_METHOD *meth_in)
+{
+ /* Create our context*/
+ static std::map<std::string, SSL_CTX *> client_contexts;
+ if (client_contexts.find(context) == client_contexts.end())
+ {
+ SSL_METHOD *meth = meth_in ? meth_in : SSLv3_method();
+ m_ssl_ctx = client_contexts[context] = SSL_CTX_new(meth);
+ SSL_CTX_set_mode(m_ssl_ctx, SSL_MODE_AUTO_RETRY);
+ }
+ else
+ {
+ m_ssl_ctx = client_contexts[context];
+ }
+}
+
+
+void TcpSocket::InitializeContext(const std::string& context,const std::string& keyfile,const std::string& password,SSL_METHOD *meth_in)
+{
+ /* Create our context*/
+ static std::map<std::string, SSL_CTX *> server_contexts;
+ if (server_contexts.find(context) == server_contexts.end())
+ {
+ SSL_METHOD *meth = meth_in ? meth_in : SSLv3_method();
+ m_ssl_ctx = server_contexts[context] = SSL_CTX_new(meth);
+ SSL_CTX_set_mode(m_ssl_ctx, SSL_MODE_AUTO_RETRY);
+ // session id
+ if (context.size())
+ SSL_CTX_set_session_id_context(m_ssl_ctx, (const unsigned char *)context.c_str(), (unsigned int)context.size());
+ else
+ SSL_CTX_set_session_id_context(m_ssl_ctx, (const unsigned char *)"--empty--", 9);
+ }
+ else
+ {
+ m_ssl_ctx = server_contexts[context];
+ }
+
+ /* Load our keys and certificates*/
+ if (!(SSL_CTX_use_certificate_file(m_ssl_ctx, keyfile.c_str(), SSL_FILETYPE_PEM)))
+ {
+ Handler().LogError(this, "TcpSocket InitializeContext", 0, "Couldn't read certificate file " + keyfile, LOG_LEVEL_FATAL);
+ }
+
+ m_password = password;
+ SSL_CTX_set_default_passwd_cb(m_ssl_ctx, SSL_password_cb);
+ SSL_CTX_set_default_passwd_cb_userdata(m_ssl_ctx, this);
+ if (!(SSL_CTX_use_PrivateKey_file(m_ssl_ctx, keyfile.c_str(), SSL_FILETYPE_PEM)))
+ {
+ Handler().LogError(this, "TcpSocket InitializeContext", 0, "Couldn't read private key file " + keyfile, LOG_LEVEL_FATAL);
+ }
+}
+
+
+void TcpSocket::InitializeContext(const std::string& context,const std::string& certfile,const std::string& keyfile,const std::string& password,SSL_METHOD *meth_in)
+{
+ /* Create our context*/
+ static std::map<std::string, SSL_CTX *> server_contexts;
+ if (server_contexts.find(context) == server_contexts.end())
+ {
+ SSL_METHOD *meth = meth_in ? meth_in : SSLv3_method();
+ m_ssl_ctx = server_contexts[context] = SSL_CTX_new(meth);
+ SSL_CTX_set_mode(m_ssl_ctx, SSL_MODE_AUTO_RETRY);
+ // session id
+ if (context.size())
+ SSL_CTX_set_session_id_context(m_ssl_ctx, (const unsigned char *)context.c_str(), (unsigned int)context.size());
+ else
+ SSL_CTX_set_session_id_context(m_ssl_ctx, (const unsigned char *)"--empty--", 9);
+ }
+ else
+ {
+ m_ssl_ctx = server_contexts[context];
+ }
+
+ /* Load our keys and certificates*/
+ if (!(SSL_CTX_use_certificate_file(m_ssl_ctx, certfile.c_str(), SSL_FILETYPE_PEM)))
+ {
+ Handler().LogError(this, "TcpSocket InitializeContext", 0, "Couldn't read certificate file " + keyfile, LOG_LEVEL_FATAL);
+ }
+
+ m_password = password;
+ SSL_CTX_set_default_passwd_cb(m_ssl_ctx, SSL_password_cb);
+ SSL_CTX_set_default_passwd_cb_userdata(m_ssl_ctx, this);
+ if (!(SSL_CTX_use_PrivateKey_file(m_ssl_ctx, keyfile.c_str(), SSL_FILETYPE_PEM)))
+ {
+ Handler().LogError(this, "TcpSocket InitializeContext", 0, "Couldn't read private key file " + keyfile, LOG_LEVEL_FATAL);
+ }
+}
+
+
+int TcpSocket::SSL_password_cb(char *buf,int num,int rwflag,void *userdata)
+{
+ Socket *p0 = static_cast<Socket *>(userdata);
+ TcpSocket *p = dynamic_cast<TcpSocket *>(p0);
+ std::string pw = p ? p -> GetPassword() : "";
+ if ( (size_t)num < pw.size() + 1)
+ {
+ return 0;
+ }
+ strcpy(buf,pw.c_str());
+ return (int)pw.size();
+}
+#endif // HAVE_OPENSSL
+
+
+int TcpSocket::Close()
+{
+ if (GetSocket() == INVALID_SOCKET) // this could happen
+ {
+ Handler().LogError(this, "Socket::Close", 0, "file descriptor invalid", LOG_LEVEL_WARNING);
+ return 0;
+ }
+ int n;
+ SetNonblocking(true);
+ if (IsConnected() && !(GetShutdown() & SHUT_WR))
+ {
+ if (shutdown(GetSocket(), SHUT_WR) == -1)
+ {
+ // failed...
+ Handler().LogError(this, "shutdown", Errno, StrError(Errno), LOG_LEVEL_ERROR);
+ }
+ }
+ //
+ char tmp[1000];
+ if ((n = recv(GetSocket(),tmp,1000,0)) >= 0)
+ {
+ if (n)
+ {
+ Handler().LogError(this, "read() after shutdown", n, "bytes read", LOG_LEVEL_WARNING);
+ }
+ }
+#ifdef HAVE_OPENSSL
+ if (IsSSL() && m_ssl)
+ SSL_shutdown(m_ssl);
+ if (m_ssl)
+ {
+ SSL_free(m_ssl);
+ m_ssl = NULL;
+ }
+#endif
+ return Socket::Close();
+}
+
+
+#ifdef HAVE_OPENSSL
+SSL_CTX *TcpSocket::GetSslContext()
+{
+ if (!m_ssl_ctx)
+ Handler().LogError(this, "GetSslContext", 0, "SSL Context is NULL; check InitSSLServer/InitSSLClient", LOG_LEVEL_WARNING);
+ return m_ssl_ctx;
+}
+
+SSL *TcpSocket::GetSsl()
+{
+ if (!m_ssl)
+ Handler().LogError(this, "GetSsl", 0, "SSL is NULL; check InitSSLServer/InitSSLClient", LOG_LEVEL_WARNING);
+ return m_ssl;
+}
+#endif
+
+
+#ifdef ENABLE_RECONNECT
+void TcpSocket::SetReconnect(bool x)
+{
+ m_b_reconnect = x;
+}
+#endif
+
+
+void TcpSocket::OnRawData(const char *buf_in,size_t len)
+{
+}
+
+
+size_t TcpSocket::GetInputLength()
+{
+ return ibuf.GetLength();
+}
+
+
+size_t TcpSocket::GetOutputLength()
+{
+ return m_output_length;
+}
+
+
+uint64_t TcpSocket::GetBytesReceived(bool clear)
+{
+ uint64_t z = m_bytes_received;
+ if (clear)
+ m_bytes_received = 0;
+ return z;
+}
+
+
+uint64_t TcpSocket::GetBytesSent(bool clear)
+{
+ uint64_t z = m_bytes_sent;
+ if (clear)
+ m_bytes_sent = 0;
+ return z;
+}
+
+
+#ifdef ENABLE_RECONNECT
+bool TcpSocket::Reconnect()
+{
+ return m_b_reconnect;
+}
+
+
+void TcpSocket::SetIsReconnect(bool x)
+{
+ m_b_is_reconnect = x;
+}
+
+
+bool TcpSocket::IsReconnect()
+{
+ return m_b_is_reconnect;
+}
+#endif
+
+
+#ifdef HAVE_OPENSSL
+const std::string& TcpSocket::GetPassword()
+{
+ return m_password;
+}
+#endif
+
+
+void TcpSocket::DisableInputBuffer(bool x)
+{
+ m_b_input_buffer_disabled = x;
+}
+
+
+void TcpSocket::OnOptions(int family,int type,int protocol,SOCKET s)
+{
+DEB( fprintf(stderr, "Socket::OnOptions()\n");)
+#ifdef SO_NOSIGPIPE
+ SetSoNosigpipe(true);
+#endif
+ SetSoReuseaddr(true);
+ SetSoKeepalive(true);
+}
+
+
+void TcpSocket::SetLineProtocol(bool x)
+{
+ StreamSocket::SetLineProtocol(x);
+ DisableInputBuffer(x);
+}
+
+
+bool TcpSocket::SetTcpNodelay(bool x)
+{
+#ifdef TCP_NODELAY
+ int optval = x ? 1 : 0;
+ if (setsockopt(GetSocket(), IPPROTO_TCP, TCP_NODELAY, (char *)&optval, sizeof(optval)) == -1)
+ {
+ Handler().LogError(this, "setsockopt(IPPROTO_TCP, TCP_NODELAY)", Errno, StrError(Errno), LOG_LEVEL_FATAL);
+ return false;
+ }
+ return true;
+#else
+ Handler().LogError(this, "socket option not available", 0, "TCP_NODELAY", LOG_LEVEL_INFO);
+ return false;
+#endif
+}
+
+
+TcpSocket::CircularBuffer::CircularBuffer(size_t size)
+:buf(new char[2 * size])
+,m_max(size)
+,m_q(0)
+,m_b(0)
+,m_t(0)
+,m_count(0)
+{
+}
+
+
+TcpSocket::CircularBuffer::~CircularBuffer()
+{
+ delete[] buf;
+}
+
+
+bool TcpSocket::CircularBuffer::Write(const char *s,size_t l)
+{
+ if (m_q + l > m_max)
+ {
+ return false; // overflow
+ }
+ m_count += (unsigned long)l;
+ if (m_t + l > m_max) // block crosses circular border
+ {
+ size_t l1 = m_max - m_t; // size left until circular border crossing
+ // always copy full block to buffer(buf) + top pointer(m_t)
+ // because we have doubled the buffer size for performance reasons
+ memcpy(buf + m_t, s, l);
+ memcpy(buf, s + l1, l - l1);
+ m_t = l - l1;
+ m_q += l;
+ }
+ else
+ {
+ memcpy(buf + m_t, s, l);
+ memcpy(buf + m_max + m_t, s, l);
+ m_t += l;
+ if (m_t >= m_max)
+ m_t -= m_max;
+ m_q += l;
+ }
+ return true;
+}
+
+
+bool TcpSocket::CircularBuffer::Read(char *s,size_t l)
+{
+ if (l > m_q)
+ {
+ return false; // not enough chars
+ }
+ if (m_b + l > m_max) // block crosses circular border
+ {
+ size_t l1 = m_max - m_b;
+ if (s)
+ {
+ memcpy(s, buf + m_b, l1);
+ memcpy(s + l1, buf, l - l1);
+ }
+ m_b = l - l1;
+ m_q -= l;
+ }
+ else
+ {
+ if (s)
+ {
+ memcpy(s, buf + m_b, l);
+ }
+ m_b += l;
+ if (m_b >= m_max)
+ m_b -= m_max;
+ m_q -= l;
+ }
+ if (!m_q)
+ {
+ m_b = m_t = 0;
+ }
+ return true;
+}
+
+
+bool TcpSocket::CircularBuffer::Remove(size_t l)
+{
+ return Read(NULL, l);
+}
+
+
+size_t TcpSocket::CircularBuffer::GetLength()
+{
+ return m_q;
+}
+
+
+const char *TcpSocket::CircularBuffer::GetStart()
+{
+ return buf + m_b;
+}
+
+
+size_t TcpSocket::CircularBuffer::GetL()
+{
+ return (m_b + m_q > m_max) ? m_max - m_b : m_q;
+}
+
+
+size_t TcpSocket::CircularBuffer::Space()
+{
+ return m_max - m_q;
+}
+
+
+unsigned long TcpSocket::CircularBuffer::ByteCounter(bool clear)
+{
+ if (clear)
+ {
+ unsigned long x = m_count;
+ m_count = 0;
+ return x;
+ }
+ return m_count;
+}
+
+
+std::string TcpSocket::CircularBuffer::ReadString(size_t l)
+{
+ char *sz = new char[l + 1];
+ if (!Read(sz, l)) // failed, debug printout in Read() method
+ {
+ delete[] sz;
+ return "";
+ }
+ sz[l] = 0;
+ std::string tmp = sz;
+ delete[] sz;
+ return tmp;
+}
+
+
+void TcpSocket::OnConnectTimeout()
+{
+ Handler().LogError(this, "connect", -1, "connect timeout", LOG_LEVEL_FATAL);
+#ifdef ENABLE_SOCKS4
+ if (Socks4())
+ {
+ OnSocks4ConnectFailed();
+ // retry direct connection
+ }
+ else
+#endif
+ if (GetConnectionRetry() == -1 ||
+ (GetConnectionRetry() && GetConnectionRetries() < GetConnectionRetry()) )
+ {
+ IncreaseConnectionRetries();
+ // ask socket via OnConnectRetry callback if we should continue trying
+ if (OnConnectRetry())
+ {
+ SetRetryClientConnect();
+ }
+ else
+ {
+ SetCloseAndDelete( true );
+ /// \todo state reason why connect failed
+ OnConnectFailed();
+ }
+ }
+ else
+ {
+ SetCloseAndDelete(true);
+ /// \todo state reason why connect failed
+ OnConnectFailed();
+ }
+ //
+ SetConnecting(false);
+}
+
+
+#ifdef _WIN32
+void TcpSocket::OnException()
+{
+ if (Connecting())
+ {
+#ifdef ENABLE_SOCKS4
+ if (Socks4())
+ OnSocks4ConnectFailed();
+ else
+#endif
+ if (GetConnectionRetry() == -1 ||
+ (GetConnectionRetry() &&
+ GetConnectionRetries() < GetConnectionRetry() ))
+ {
+ // even though the connection failed at once, only retry after
+ // the connection timeout
+ // should we even try to connect again, when CheckConnect returns
+ // false it's because of a connection error - not a timeout...
+ }
+ else
+ {
+ SetConnecting(false); // tnx snibbe
+ SetCloseAndDelete();
+ OnConnectFailed();
+ }
+ return;
+ }
+ // %! exception doesn't always mean something bad happened, this code should be reworked
+ // errno valid here?
+ int err = SoError();
+ Handler().LogError(this, "exception on select", err, StrError(err), LOG_LEVEL_FATAL);
+ SetCloseAndDelete();
+}
+#endif // _WIN32
+
+
+int TcpSocket::Protocol()
+{
+ return IPPROTO_TCP;
+}
+
+
+void TcpSocket::SetTransferLimit(size_t sz)
+{
+ m_transfer_limit = sz;
+}
+
+
+void TcpSocket::OnTransferLimit()
+{
+}
+
+
+#ifdef SOCKETS_NAMESPACE
+}
+#endif
+
diff --git a/Sockets/TcpSocket.h b/Sockets/TcpSocket.h
new file mode 100644
index 0000000..47f7d15
--- /dev/null
+++ b/Sockets/TcpSocket.h
@@ -0,0 +1,355 @@
+/** \file TcpSocket.h
+ ** \date 2004-02-13
+ ** \author grymse@alhem.net
+**/
+/*
+Copyright (C) 2004-2007 Anders Hedstrom
+
+This library is made available under the terms of the GNU GPL.
+
+If you would like to use this library in a closed-source application,
+a separate license agreement is available. For information about
+the closed-source license agreement for the C++ sockets library,
+please visit http://www.alhem.net/Sockets/license.html and/or
+email license@alhem.net.
+
+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.
+*/
+#ifndef _SOCKETS_TcpSocket_H
+#define _SOCKETS_TcpSocket_H
+#include "sockets-config.h"
+#include "StreamSocket.h"
+#ifdef HAVE_OPENSSL
+#include <openssl/ssl.h>
+#include "SSLInitializer.h"
+#endif
+
+
+#define TCP_BUFSIZE_READ 16400
+#define TCP_OUTPUT_CAPACITY 1024000
+
+
+#ifdef SOCKETS_NAMESPACE
+namespace SOCKETS_NAMESPACE {
+#endif
+
+class SocketAddress;
+
+
+/** Socket implementation for TCP.
+ \ingroup basic */
+class TcpSocket : public StreamSocket
+{
+ /** \defgroup internal Internal utility */
+protected:
+ /** Buffer class containing one read/write circular buffer.
+ \ingroup internal */
+ class CircularBuffer
+ {
+ public:
+ CircularBuffer(size_t size);
+ ~CircularBuffer();
+
+ /** append l bytes from p to buffer */
+ bool Write(const char *p,size_t l);
+ /** copy l bytes from buffer to dest */
+ bool Read(char *dest,size_t l);
+ /** skip l bytes from buffer */
+ bool Remove(size_t l);
+ /** read l bytes from buffer, returns as string. */
+ std::string ReadString(size_t l);
+
+ /** total buffer length */
+ size_t GetLength();
+ /** pointer to circular buffer beginning */
+ const char *GetStart();
+ /** return number of bytes from circular buffer beginning to buffer physical end */
+ size_t GetL();
+ /** return free space in buffer, number of bytes until buffer overrun */
+ size_t Space();
+
+ /** return total number of bytes written to this buffer, ever */
+ unsigned long ByteCounter(bool clear = false);
+
+ private:
+ CircularBuffer(const CircularBuffer& s) {}
+ CircularBuffer& operator=(const CircularBuffer& ) { return *this; }
+ char *buf;
+ size_t m_max;
+ size_t m_q;
+ size_t m_b;
+ size_t m_t;
+ unsigned long m_count;
+ };
+ /** Output buffer struct.
+ \ingroup internal */
+ struct OUTPUT {
+ OUTPUT() : _b(0), _t(0), _q(0) {}
+ OUTPUT(const char *buf, size_t len) : _b(0), _t(len), _q(len) {
+ memcpy(_buf, buf, len);
+ }
+ size_t Space() {
+ return TCP_OUTPUT_CAPACITY - _t;
+ }
+ void Add(const char *buf, size_t len) {
+ memcpy(_buf + _t, buf, len);
+ _t += len;
+ _q += len;
+ }
+ size_t Remove(size_t len) {
+ _b += len;
+ _q -= len;
+ return _q;
+ }
+ const char *Buf() {
+ return _buf + _b;
+ }
+ size_t Len() {
+ return _q;
+ }
+ size_t _b;
+ size_t _t;
+ size_t _q;
+ char _buf[TCP_OUTPUT_CAPACITY];
+ };
+ typedef std::list<OUTPUT *> output_l;
+
+public:
+ /** Constructor with standard values on input/output buffers. */
+ TcpSocket(ISocketHandler& );
+ /** Constructor with custom values for i/o buffer.
+ \param h ISocketHandler reference
+ \param isize Input buffer size
+ \param osize Output buffer size */
+ TcpSocket(ISocketHandler& h,size_t isize,size_t osize);
+ ~TcpSocket();
+
+ /** Open a connection to a remote server.
+ If you want your socket to connect to a server,
+ always call Open before Add'ing a socket to the sockethandler.
+ If not, the connection attempt will not be monitored by the
+ socket handler...
+ \param ip IP address
+ \param port Port number
+ \param skip_socks Do not use socks4 even if configured */
+ bool Open(ipaddr_t ip,port_t port,bool skip_socks = false);
+#ifdef ENABLE_IPV6
+#ifdef IPPROTO_IPV6
+ /** Open connection.
+ \param ip Ipv6 address
+ \param port Port number
+ \param skip_socks Do not use socks4 even if configured */
+ bool Open(in6_addr ip,port_t port,bool skip_socks = false);
+#endif
+#endif
+ bool Open(SocketAddress&,bool skip_socks = false);
+ bool Open(SocketAddress&,SocketAddress& bind_address,bool skip_socks = false);
+ /** Open connection.
+ \param host Hostname
+ \param port Port number */
+ bool Open(const std::string &host,port_t port);
+
+ /** Connect timeout callback. */
+ void OnConnectTimeout();
+#ifdef _WIN32
+ /** Connection failed reported as exception on win32 */
+ void OnException();
+#endif
+
+ /** Close file descriptor - internal use only.
+ \sa SetCloseAndDelete */
+ int Close();
+
+ /** Send a string.
+ \param s String to send
+ \param f Dummy flags -- not used */
+ void Send(const std::string &s,int f = 0);
+ /** Send string using printf formatting. */
+ void Sendf(const char *format, ...);
+ /** Send buffer of bytes.
+ \param buf Buffer pointer
+ \param len Length of data
+ \param f Dummy flags -- not used */
+ void SendBuf(const char *buf,size_t len,int f = 0);
+ /** This callback is executed after a successful read from the socket.
+ \param buf Pointer to the data
+ \param len Length of the data */
+ virtual void OnRawData(const char *buf,size_t len);
+
+ /** Called when output buffer has been sent.
+ Note: Will only be called IF the output buffer has been used.
+ Send's that was successful without needing the output buffer
+ will not generate a call to this method. */
+ virtual void OnWriteComplete();
+ /** Number of bytes in input buffer. */
+ size_t GetInputLength();
+ /** Number of bytes in output buffer. */
+ size_t GetOutputLength();
+
+ /** Callback fires when a socket in line protocol has read one full line.
+ \param line Line read */
+ void OnLine(const std::string& line);
+ /** Get counter of number of bytes received. */
+ uint64_t GetBytesReceived(bool clear = false);
+ /** Get counter of number of bytes sent. */
+ uint64_t GetBytesSent(bool clear = false);
+
+ /** Socks4 specific callback. */
+ void OnSocks4Connect();
+ /** Socks4 specific callback. */
+ void OnSocks4ConnectFailed();
+ /** Socks4 specific callback.
+ \return 'need_more' */
+ bool OnSocks4Read();
+
+#ifdef ENABLE_RESOLVER
+ /** Callback executed when resolver thread has finished a resolve request. */
+ void OnResolved(int id,ipaddr_t a,port_t port);
+#ifdef ENABLE_IPV6
+ void OnResolved(int id,in6_addr& a,port_t port);
+#endif
+#endif
+#ifdef HAVE_OPENSSL
+ /** Callback for 'New' ssl support - replaces SSLSocket. Internal use. */
+ void OnSSLConnect();
+ /** Callback for 'New' ssl support - replaces SSLSocket. Internal use. */
+ void OnSSLAccept();
+ /** This method must be implemented to initialize
+ the ssl context for an outgoing connection. */
+ virtual void InitSSLClient();
+ /** This method must be implemented to initialize
+ the ssl context for an incoming connection. */
+ virtual void InitSSLServer();
+#endif
+
+#ifdef ENABLE_RECONNECT
+ /** Flag that says a broken connection will try to reconnect. */
+ void SetReconnect(bool = true);
+ /** Check reconnect on lost connection flag status. */
+ bool Reconnect();
+ /** Flag to determine if a reconnect is in progress. */
+ void SetIsReconnect(bool x = true);
+ /** Socket is reconnecting. */
+ bool IsReconnect();
+#endif
+
+ void DisableInputBuffer(bool = true);
+
+ void OnOptions(int,int,int,SOCKET);
+
+ void SetLineProtocol(bool = true);
+
+ // TCP options
+ bool SetTcpNodelay(bool = true);
+
+ virtual int Protocol();
+
+ /** Trigger limit for callback OnTransferLimit. */
+ void SetTransferLimit(size_t sz);
+ /** This callback fires when the output buffer drops below the value
+ set by SetTransferLimit. Default: 0 (disabled). */
+ virtual void OnTransferLimit();
+
+protected:
+ TcpSocket(const TcpSocket& );
+ void OnRead();
+ void OnRead( char *buf, size_t n );
+ void OnWrite();
+#ifdef HAVE_OPENSSL
+ /** SSL; Initialize ssl context for a client socket.
+ \param meth_in SSL method */
+ void InitializeContext(const std::string& context, SSL_METHOD *meth_in = NULL);
+ /** SSL; Initialize ssl context for a server socket.
+ \param keyfile Combined private key/certificate file
+ \param password Password for private key
+ \param meth_in SSL method */
+ void InitializeContext(const std::string& context, const std::string& keyfile, const std::string& password, SSL_METHOD *meth_in = NULL);
+ /** SSL; Initialize ssl context for a server socket.
+ \param certfile Separate certificate file
+ \param keyfile Combined private key/certificate file
+ \param password Password for private key
+ \param meth_in SSL method */
+ void InitializeContext(const std::string& context, const std::string& certfile, const std::string& keyfile, const std::string& password, SSL_METHOD *meth_in = NULL);
+ /** SSL; Password callback method. */
+static int SSL_password_cb(char *buf,int num,int rwflag,void *userdata);
+ /** SSL; Get pointer to ssl context structure. */
+ virtual SSL_CTX *GetSslContext();
+ /** SSL; Get pointer to ssl structure. */
+ virtual SSL *GetSsl();
+ /** ssl; still negotiating connection. */
+ bool SSLNegotiate();
+ /** SSL; Get ssl password. */
+ const std::string& GetPassword();
+#endif
+
+ CircularBuffer ibuf; ///< Circular input buffer
+
+private:
+ TcpSocket& operator=(const TcpSocket& ) { return *this; }
+
+ /** the actual send() */
+ int TryWrite(const char *buf, size_t len);
+ /** add data to output buffer top */
+ void Buffer(const char *buf, size_t len);
+
+ //
+ bool m_b_input_buffer_disabled;
+ uint64_t m_bytes_sent;
+ uint64_t m_bytes_received;
+ bool m_skip_c; ///< Skip second char of CRLF or LFCR sequence in OnRead
+ char m_c; ///< First char in CRLF or LFCR sequence
+ std::string m_line; ///< Current line in line protocol mode
+#ifdef SOCKETS_DYNAMIC_TEMP
+ char *m_buf; ///< temporary read buffer
+#endif
+ output_l m_obuf; ///< output buffer
+ OUTPUT *m_obuf_top; ///< output buffer on top
+ size_t m_transfer_limit;
+ size_t m_output_length;
+
+#ifdef HAVE_OPENSSL
+static SSLInitializer m_ssl_init;
+ SSL_CTX *m_ssl_ctx; ///< ssl context
+ SSL *m_ssl; ///< ssl 'socket'
+ BIO *m_sbio; ///< ssl bio
+ std::string m_password; ///< ssl password
+#endif
+
+#ifdef ENABLE_SOCKS4
+ int m_socks4_state; ///< socks4 support
+ char m_socks4_vn; ///< socks4 support, temporary variable
+ char m_socks4_cd; ///< socks4 support, temporary variable
+ unsigned short m_socks4_dstport; ///< socks4 support
+ unsigned long m_socks4_dstip; ///< socks4 support
+#endif
+
+#ifdef ENABLE_RESOLVER
+ int m_resolver_id; ///< Resolver id (if any) for current Open call
+#endif
+
+#ifdef ENABLE_RECONNECT
+ bool m_b_reconnect; ///< Reconnect on lost connection flag
+ bool m_b_is_reconnect; ///< Trying to reconnect
+#endif
+
+};
+
+
+#ifdef SOCKETS_NAMESPACE
+}
+#endif
+
+#endif // _SOCKETS_TcpSocket_H
+
diff --git a/Sockets/Thread.cpp b/Sockets/Thread.cpp
new file mode 100644
index 0000000..2717e32
--- /dev/null
+++ b/Sockets/Thread.cpp
@@ -0,0 +1,166 @@
+/** \file Thread.cpp
+ ** \date 2004-10-30
+ ** \author grymse@alhem.net
+**/
+/*
+Copyright (C) 2004-2007 Anders Hedstrom
+
+This library is made available under the terms of the GNU GPL.
+
+If you would like to use this library in a closed-source application,
+a separate license agreement is available. For information about
+the closed-source license agreement for the C++ sockets library,
+please visit http://www.alhem.net/Sockets/license.html and/or
+email license@alhem.net.
+
+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.
+*/
+#include <stdio.h>
+#ifdef _WIN32
+#include <process.h>
+#include "socket_include.h"
+#else
+#include <unistd.h>
+#endif
+
+#include "Thread.h"
+
+
+#ifdef SOCKETS_NAMESPACE
+namespace SOCKETS_NAMESPACE {
+#endif
+
+
+Thread::Thread(bool release)
+:m_thread(0)
+,m_running(true)
+,m_release(false)
+,m_b_delete_on_exit(false)
+,m_b_destructor(false)
+{
+#ifdef _WIN32
+// m_thread = ::CreateThread(NULL, 0, StartThread, this, 0, &m_dwThreadId);
+ m_thread = (HANDLE)_beginthreadex(NULL, 0, &StartThread, this, 0, &m_dwThreadId);
+#else
+ pthread_attr_t attr;
+
+ pthread_attr_init(&attr);
+ pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);
+ if (pthread_create(&m_thread,&attr, StartThread,this) == -1)
+ {
+ perror("Thread: create failed");
+ SetRunning(false);
+ }
+// pthread_attr_destroy(&attr);
+#endif
+ m_release = release;
+}
+
+
+Thread::~Thread()
+{
+ m_b_destructor = true;
+ if (m_running)
+ {
+ SetRelease(true);
+ SetRunning(false);
+#ifdef _WIN32
+ Sleep(1000);
+#else
+ sleep(1);
+#endif
+ }
+#ifdef _WIN32
+ if (m_thread)
+ ::CloseHandle(m_thread);
+#endif
+}
+
+
+threadfunc_t STDPREFIX Thread::StartThread(threadparam_t zz)
+{
+ Thread *p = (Thread *)zz;
+
+ while (p -> m_running && !p -> m_release)
+ {
+#ifdef _WIN32
+ Sleep(1000);
+#else
+ sleep(1);
+#endif
+ }
+ if (p -> m_running)
+ {
+ p -> Run();
+ }
+ p -> SetRunning(false); // if return
+ if (p -> DeleteOnExit() && !p -> IsDestructor())
+ {
+ delete p;
+ }
+#ifdef _WIN32
+ _endthreadex(0);
+#endif
+ return (threadfunc_t)NULL;
+}
+
+
+bool Thread::IsRunning()
+{
+ return m_running;
+}
+
+
+void Thread::SetRunning(bool x)
+{
+ m_running = x;
+}
+
+
+bool Thread::IsReleased()
+{
+ return m_release;
+}
+
+
+void Thread::SetRelease(bool x)
+{
+ m_release = x;
+}
+
+
+bool Thread::DeleteOnExit()
+{
+ return m_b_delete_on_exit;
+}
+
+
+void Thread::SetDeleteOnExit(bool x)
+{
+ m_b_delete_on_exit = x;
+}
+
+
+bool Thread::IsDestructor()
+{
+ return m_b_destructor;
+}
+
+
+#ifdef SOCKETS_NAMESPACE
+}
+#endif
+
+
diff --git a/Sockets/Thread.h b/Sockets/Thread.h
new file mode 100644
index 0000000..d784a15
--- /dev/null
+++ b/Sockets/Thread.h
@@ -0,0 +1,100 @@
+/** \file Thread.h
+ ** \date 2004-10-30
+ ** \author grymse@alhem.net
+**/
+/*
+Copyright (C) 2004-2007 Anders Hedstrom
+
+This library is made available under the terms of the GNU GPL.
+
+If you would like to use this library in a closed-source application,
+a separate license agreement is available. For information about
+the closed-source license agreement for the C++ sockets library,
+please visit http://www.alhem.net/Sockets/license.html and/or
+email license@alhem.net.
+
+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.
+*/
+#ifndef _SOCKETS_Thread_H
+#define _SOCKETS_Thread_H
+
+#include "sockets-config.h"
+#ifdef SOCKETS_NAMESPACE
+namespace SOCKETS_NAMESPACE {
+#endif
+
+#ifdef _WIN32
+// to be
+//typedef DWORD threadfunc_t;
+//typedef LPVOID threadparam_t;
+//#define STDPREFIX WINAPI
+typedef unsigned threadfunc_t;
+typedef void * threadparam_t;
+#define STDPREFIX __stdcall
+#else
+#include <pthread.h>
+
+typedef void * threadfunc_t;
+typedef void * threadparam_t;
+#define STDPREFIX
+#endif
+
+/** \defgroup threading Threading */
+/** Thread base class.
+The Thread class is used by the resolver (ResolvServer) and running a detached socket (SocketThread).
+When you know some processing will take a long time and will freeze up a socket, there is always the
+possibility to call Detach() on that socket before starting the processing.
+When the OnDetached() callback is later called the processing can continue, now in its own thread.
+ \ingroup threading */
+class Thread
+{
+public:
+ Thread(bool release = true);
+ virtual ~Thread();
+
+ static threadfunc_t STDPREFIX StartThread(threadparam_t);
+
+ virtual void Run() = 0;
+
+ bool IsRunning();
+ void SetRunning(bool x);
+ bool IsReleased();
+ void SetRelease(bool x);
+ bool DeleteOnExit();
+ void SetDeleteOnExit(bool x = true);
+ bool IsDestructor();
+
+private:
+ Thread(const Thread& ) {}
+ Thread& operator=(const Thread& ) { return *this; }
+#ifdef _WIN32
+ HANDLE m_thread;
+ unsigned m_dwThreadId;
+#else
+ pthread_t m_thread;
+#endif
+ bool m_running;
+ bool m_release;
+ bool m_b_delete_on_exit;
+ bool m_b_destructor;
+};
+
+
+#ifdef SOCKETS_NAMESPACE
+}
+#endif
+
+#endif // _SOCKETS_Thread_H
+
diff --git a/Sockets/UdpSocket.cpp b/Sockets/UdpSocket.cpp
new file mode 100644
index 0000000..75bebf2
--- /dev/null
+++ b/Sockets/UdpSocket.cpp
@@ -0,0 +1,843 @@
+/** \file UdpSocket.cpp
+ ** \date 2004-02-13
+ ** \author grymse@alhem.net
+**/
+/*
+Copyright (C) 2004-2007 Anders Hedstrom
+
+This library is made available under the terms of the GNU GPL.
+
+If you would like to use this library in a closed-source application,
+a separate license agreement is available. For information about
+the closed-source license agreement for the C++ sockets library,
+please visit http://www.alhem.net/Sockets/license.html and/or
+email license@alhem.net.
+
+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
+#ifdef _MSC_VER
+#pragma warning(disable:4786)
+#endif
+#include <stdlib.h>
+#else
+#include <errno.h>
+#endif
+
+#include "ISocketHandler.h"
+#include "UdpSocket.h"
+#include "Utility.h"
+#include "Ipv4Address.h"
+#include "Ipv6Address.h"
+#ifdef ENABLE_EXCEPTIONS
+#include "Exception.h"
+#endif
+// include this to see strange sights
+//#include <linux/in6.h>
+
+
+#ifdef SOCKETS_NAMESPACE
+namespace SOCKETS_NAMESPACE {
+#endif
+
+
+UdpSocket::UdpSocket(ISocketHandler& h, int ibufsz, bool ipv6, int retries) : Socket(h)
+, m_ibuf(new char[ibufsz])
+, m_ibufsz(ibufsz)
+, m_bind_ok(false)
+, m_port(0)
+, m_last_size_written(-1)
+, m_retries(retries)
+, m_b_read_ts(false)
+{
+#ifdef ENABLE_IPV6
+#ifdef IPPROTO_IPV6
+ SetIpv6(ipv6);
+#endif
+#endif
+}
+
+
+UdpSocket::~UdpSocket()
+{
+ Close();
+ delete[] m_ibuf;
+}
+
+
+int UdpSocket::Bind(port_t &port, int range)
+{
+#ifdef ENABLE_IPV6
+#ifdef IPPROTO_IPV6
+ if (IsIpv6())
+ {
+ Ipv6Address ad(port);
+ return Bind(ad, range);
+ }
+#endif
+#endif
+ Ipv4Address ad(port);
+ return Bind(ad, range);
+}
+
+
+int UdpSocket::Bind(const std::string& intf, port_t &port, int range)
+{
+#ifdef ENABLE_IPV6
+#ifdef IPPROTO_IPV6
+ if (IsIpv6())
+ {
+ Ipv6Address ad(intf, port);
+ if (ad.IsValid())
+ {
+ return Bind(ad, range);
+ }
+ SetCloseAndDelete();
+ return -1;
+ }
+#endif
+#endif
+ Ipv4Address ad(intf, port);
+ if (ad.IsValid())
+ {
+ return Bind(ad, range);
+ }
+ SetCloseAndDelete();
+ return -1;
+}
+
+
+int UdpSocket::Bind(ipaddr_t a, port_t &port, int range)
+{
+ Ipv4Address ad(a, port);
+ return Bind(ad, range);
+}
+
+
+#ifdef ENABLE_IPV6
+#ifdef IPPROTO_IPV6
+int UdpSocket::Bind(in6_addr a, port_t &port, int range)
+{
+ Ipv6Address ad(a, port);
+ return Bind(ad, range);
+}
+#endif
+#endif
+
+
+int UdpSocket::Bind(SocketAddress& ad, int range)
+{
+ if (GetSocket() == INVALID_SOCKET)
+ {
+ Attach(CreateSocket(ad.GetFamily(), SOCK_DGRAM, "udp"));
+ }
+ if (GetSocket() != INVALID_SOCKET)
+ {
+ SetNonblocking(true);
+ int n = bind(GetSocket(), ad, ad);
+ int tries = range;
+ while (n == -1 && tries--)
+ {
+ ad.SetPort(ad.GetPort() + 1);
+ n = bind(GetSocket(), ad, ad);
+ }
+ if (n == -1)
+ {
+ Handler().LogError(this, "bind", Errno, StrError(Errno), LOG_LEVEL_FATAL);
+ SetCloseAndDelete();
+#ifdef ENABLE_EXCEPTIONS
+ throw Exception("bind() failed for UdpSocket, port:range: " + Utility::l2string(ad.GetPort()) + ":" + Utility::l2string(range));
+#endif
+ return -1;
+ }
+ m_bind_ok = true;
+ m_port = ad.GetPort();
+ return 0;
+ }
+ return -1;
+}
+
+
+/** if you wish to use Send, first Open a connection */
+bool UdpSocket::Open(ipaddr_t l, port_t port)
+{
+ Ipv4Address ad(l, port);
+ return Open(ad);
+}
+
+
+bool UdpSocket::Open(const std::string& host, port_t port)
+{
+#ifdef ENABLE_IPV6
+#ifdef IPPROTO_IPV6
+ if (IsIpv6())
+ {
+ Ipv6Address ad(host, port);
+ if (ad.IsValid())
+ {
+ return Open(ad);
+ }
+ return false;
+ }
+#endif
+#endif
+ Ipv4Address ad(host, port);
+ if (ad.IsValid())
+ {
+ return Open(ad);
+ }
+ return false;
+}
+
+
+#ifdef ENABLE_IPV6
+#ifdef IPPROTO_IPV6
+bool UdpSocket::Open(struct in6_addr& a, port_t port)
+{
+ Ipv6Address ad(a, port);
+ return Open(ad);
+}
+#endif
+#endif
+
+
+bool UdpSocket::Open(SocketAddress& ad)
+{
+ if (GetSocket() == INVALID_SOCKET)
+ {
+ Attach(CreateSocket(ad.GetFamily(), SOCK_DGRAM, "udp"));
+ }
+ if (GetSocket() != INVALID_SOCKET)
+ {
+ SetNonblocking(true);
+ if (connect(GetSocket(), ad, ad) == -1)
+ {
+ Handler().LogError(this, "connect", Errno, StrError(Errno), LOG_LEVEL_FATAL);
+ SetCloseAndDelete();
+ return false;
+ }
+ SetConnected();
+ return true;
+ }
+ return false;
+}
+
+
+void UdpSocket::CreateConnection()
+{
+#ifdef ENABLE_IPV6
+#ifdef IPPROTO_IPV6
+ if (IsIpv6())
+ {
+ if (GetSocket() == INVALID_SOCKET)
+ {
+ SOCKET s = CreateSocket(AF_INET6, SOCK_DGRAM, "udp");
+ if (s == INVALID_SOCKET)
+ {
+ return;
+ }
+ SetNonblocking(true, s);
+ Attach(s);
+ }
+ return;
+ }
+#endif
+#endif
+ if (GetSocket() == INVALID_SOCKET)
+ {
+ SOCKET s = CreateSocket(AF_INET, SOCK_DGRAM, "udp");
+ if (s == INVALID_SOCKET)
+ {
+ return;
+ }
+ SetNonblocking(true, s);
+ Attach(s);
+ }
+}
+
+
+/** send to specified address */
+void UdpSocket::SendToBuf(const std::string& h, port_t p, const char *data, int len, int flags)
+{
+#ifdef ENABLE_IPV6
+#ifdef IPPROTO_IPV6
+ if (IsIpv6())
+ {
+ Ipv6Address ad(h, p);
+ if (ad.IsValid())
+ {
+ SendToBuf(ad, data, len, flags);
+ }
+ return;
+ }
+#endif
+#endif
+ Ipv4Address ad(h, p);
+ if (ad.IsValid())
+ {
+ SendToBuf(ad, data, len, flags);
+ }
+}
+
+
+/** send to specified address */
+void UdpSocket::SendToBuf(ipaddr_t a, port_t p, const char *data, int len, int flags)
+{
+ Ipv4Address ad(a, p);
+ SendToBuf(ad, data, len, flags);
+}
+
+
+#ifdef ENABLE_IPV6
+#ifdef IPPROTO_IPV6
+void UdpSocket::SendToBuf(in6_addr a, port_t p, const char *data, int len, int flags)
+{
+ Ipv6Address ad(a, p);
+ SendToBuf(ad, data, len, flags);
+}
+#endif
+#endif
+
+
+void UdpSocket::SendToBuf(SocketAddress& ad, const char *data, int len, int flags)
+{
+ if (GetSocket() == INVALID_SOCKET)
+ {
+ Attach(CreateSocket(ad.GetFamily(), SOCK_DGRAM, "udp"));
+ }
+ if (GetSocket() != INVALID_SOCKET)
+ {
+ SetNonblocking(true);
+ if ((m_last_size_written = sendto(GetSocket(), data, len, flags, ad, ad)) == -1)
+ {
+ Handler().LogError(this, "sendto", Errno, StrError(Errno), LOG_LEVEL_ERROR);
+ }
+ }
+}
+
+
+void UdpSocket::SendTo(const std::string& a, port_t p, const std::string& str, int flags)
+{
+ SendToBuf(a, p, str.c_str(), (int)str.size(), flags);
+}
+
+
+void UdpSocket::SendTo(ipaddr_t a, port_t p, const std::string& str, int flags)
+{
+ SendToBuf(a, p, str.c_str(), (int)str.size(), flags);
+}
+
+
+#ifdef ENABLE_IPV6
+#ifdef IPPROTO_IPV6
+void UdpSocket::SendTo(in6_addr a, port_t p, const std::string& str, int flags)
+{
+ SendToBuf(a, p, str.c_str(), (int)str.size(), flags);
+}
+#endif
+#endif
+
+
+void UdpSocket::SendTo(SocketAddress& ad, const std::string& str, int flags)
+{
+ SendToBuf(ad, str.c_str(), (int)str.size(), flags);
+}
+
+
+/** send to connected address */
+void UdpSocket::SendBuf(const char *data, size_t len, int flags)
+{
+ if (!IsConnected())
+ {
+ Handler().LogError(this, "SendBuf", 0, "not connected", LOG_LEVEL_ERROR);
+ return;
+ }
+ if ((m_last_size_written = send(GetSocket(), data, (int)len, flags)) == -1)
+ {
+ Handler().LogError(this, "send", Errno, StrError(Errno), LOG_LEVEL_ERROR);
+ }
+}
+
+
+void UdpSocket::Send(const std::string& str, int flags)
+{
+ SendBuf(str.c_str(), (int)str.size(), flags);
+}
+
+
+#ifndef _WIN32
+int UdpSocket::ReadTS(char *ioBuf, int inBufSize, struct sockaddr *from, socklen_t fromlen, struct timeval *ts)
+{
+ struct msghdr msg;
+ struct iovec vec[1];
+ union {
+ struct cmsghdr cm;
+ char data[CMSG_SPACE(sizeof(struct timeval))];
+ } cmsg_un;
+ struct cmsghdr *cmsg;
+ struct timeval *tv;
+
+ vec[0].iov_base = ioBuf;
+ vec[0].iov_len = inBufSize;
+
+ memset(&msg, 0, sizeof(msg));
+ memset(from, 0, fromlen);
+ memset(ioBuf, 0, inBufSize);
+ memset(&cmsg_un, 0, sizeof(cmsg_un));
+
+ msg.msg_name = (caddr_t)from;
+ msg.msg_namelen = fromlen;
+ msg.msg_iov = vec;
+ msg.msg_iovlen = 1;
+ msg.msg_control = cmsg_un.data;
+ msg.msg_controllen = sizeof(cmsg_un.data);
+ msg.msg_flags = 0;
+
+ // Original version - for reference only
+ //int n = recvfrom(GetSocket(), m_ibuf, m_ibufsz, 0, (struct sockaddr *)&sa, &sa_len);
+
+ int n = recvmsg(GetSocket(), &msg, MSG_DONTWAIT);
+
+ // now ioBuf will contain the data, as if we used recvfrom
+
+ // Now get the time
+ if(n != -1 && msg.msg_controllen >= sizeof(struct cmsghdr) && !(msg.msg_flags & MSG_CTRUNC))
+ {
+ tv = 0;
+ for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; cmsg = CMSG_NXTHDR(&msg, cmsg))
+ {
+ if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_TIMESTAMP)
+ {
+ tv = (struct timeval *)CMSG_DATA(cmsg);
+ }
+ }
+ if (tv)
+ {
+ memcpy(ts, tv, sizeof(struct timeval));
+ }
+ }
+ // The address is in network order, but that's OK right now
+ return n;
+}
+#endif
+
+
+void UdpSocket::OnRead()
+{
+#ifdef ENABLE_IPV6
+#ifdef IPPROTO_IPV6
+ if (IsIpv6())
+ {
+ struct sockaddr_in6 sa;
+ socklen_t sa_len = sizeof(sa);
+ if (m_b_read_ts)
+ {
+ struct timeval ts;
+ Utility::GetTime(&ts);
+#ifdef _WIN32
+ int n = recvfrom(GetSocket(), m_ibuf, m_ibufsz, 0, (struct sockaddr *)&sa, &sa_len);
+#else
+ int n = ReadTS(m_ibuf, m_ibufsz, (struct sockaddr *)&sa, sa_len, &ts);
+#endif
+ if (n > 0)
+ {
+ this -> OnRawData(m_ibuf, n, (struct sockaddr *)&sa, sa_len, &ts);
+ }
+ else
+ if (n == -1)
+ {
+#ifdef _WIN32
+ if (Errno != WSAEWOULDBLOCK)
+#else
+ if (Errno != EWOULDBLOCK)
+#endif
+ Handler().LogError(this, "recvfrom", Errno, StrError(Errno), LOG_LEVEL_ERROR);
+ }
+ return;
+ }
+ int n = recvfrom(GetSocket(), m_ibuf, m_ibufsz, 0, (struct sockaddr *)&sa, &sa_len);
+ int q = m_retries; // receive max 10 at one cycle
+ while (n > 0)
+ {
+ if (sa_len != sizeof(sa))
+ {
+ Handler().LogError(this, "recvfrom", 0, "unexpected address struct size", LOG_LEVEL_WARNING);
+ }
+ this -> OnRawData(m_ibuf, n, (struct sockaddr *)&sa, sa_len);
+ if (!q--)
+ break;
+ //
+ n = recvfrom(GetSocket(), m_ibuf, m_ibufsz, 0, (struct sockaddr *)&sa, &sa_len);
+ }
+ if (n == -1)
+ {
+#ifdef _WIN32
+ if (Errno != WSAEWOULDBLOCK)
+#else
+ if (Errno != EWOULDBLOCK)
+#endif
+ Handler().LogError(this, "recvfrom", Errno, StrError(Errno), LOG_LEVEL_ERROR);
+ }
+ return;
+ }
+#endif
+#endif
+ struct sockaddr_in sa;
+ socklen_t sa_len = sizeof(sa);
+ if (m_b_read_ts)
+ {
+ struct timeval ts;
+ Utility::GetTime(&ts);
+#ifdef _WIN32
+ int n = recvfrom(GetSocket(), m_ibuf, m_ibufsz, 0, (struct sockaddr *)&sa, &sa_len);
+#else
+ int n = ReadTS(m_ibuf, m_ibufsz, (struct sockaddr *)&sa, sa_len, &ts);
+#endif
+ if (n > 0)
+ {
+ this -> OnRawData(m_ibuf, n, (struct sockaddr *)&sa, sa_len, &ts);
+ }
+ else
+ if (n == -1)
+ {
+#ifdef _WIN32
+ if (Errno != WSAEWOULDBLOCK)
+#else
+ if (Errno != EWOULDBLOCK)
+#endif
+ Handler().LogError(this, "recvfrom", Errno, StrError(Errno), LOG_LEVEL_ERROR);
+ }
+ return;
+ }
+ int n = recvfrom(GetSocket(), m_ibuf, m_ibufsz, 0, (struct sockaddr *)&sa, &sa_len);
+ int q = m_retries;
+ while (n > 0)
+ {
+ if (sa_len != sizeof(sa))
+ {
+ Handler().LogError(this, "recvfrom", 0, "unexpected address struct size", LOG_LEVEL_WARNING);
+ }
+ this -> OnRawData(m_ibuf, n, (struct sockaddr *)&sa, sa_len);
+ if (!q--)
+ break;
+ //
+ n = recvfrom(GetSocket(), m_ibuf, m_ibufsz, 0, (struct sockaddr *)&sa, &sa_len);
+ }
+ if (n == -1)
+ {
+#ifdef _WIN32
+ if (Errno != WSAEWOULDBLOCK)
+#else
+ if (Errno != EWOULDBLOCK)
+#endif
+ Handler().LogError(this, "recvfrom", Errno, StrError(Errno), LOG_LEVEL_ERROR);
+ }
+}
+
+
+void UdpSocket::SetBroadcast(bool b)
+{
+ int one = 1;
+ int zero = 0;
+
+ if (GetSocket() == INVALID_SOCKET)
+ {
+ CreateConnection();
+ }
+ if (b)
+ {
+ if (setsockopt(GetSocket(), SOL_SOCKET, SO_BROADCAST, (char *) &one, sizeof(one)) == -1)
+ {
+ Handler().LogError(this, "SetBroadcast", Errno, StrError(Errno), LOG_LEVEL_WARNING);
+ }
+ }
+ else
+ {
+ if (setsockopt(GetSocket(), SOL_SOCKET, SO_BROADCAST, (char *) &zero, sizeof(zero)) == -1)
+ {
+ Handler().LogError(this, "SetBroadcast", Errno, StrError(Errno), LOG_LEVEL_WARNING);
+ }
+ }
+}
+
+
+bool UdpSocket::IsBroadcast()
+{
+ int is_broadcast = 0;
+ socklen_t size;
+
+ if (GetSocket() == INVALID_SOCKET)
+ {
+ CreateConnection();
+ }
+ if (getsockopt(GetSocket(), SOL_SOCKET, SO_BROADCAST, (char *)&is_broadcast, &size) == -1)
+ {
+ Handler().LogError(this, "IsBroadcast", Errno, StrError(Errno), LOG_LEVEL_WARNING);
+ }
+ return is_broadcast != 0;
+}
+
+
+void UdpSocket::SetMulticastTTL(int ttl)
+{
+ if (GetSocket() == INVALID_SOCKET)
+ {
+ CreateConnection();
+ }
+ if (setsockopt(GetSocket(), SOL_IP, IP_MULTICAST_TTL, (char *)&ttl, sizeof(int)) == -1)
+ {
+ Handler().LogError(this, "SetMulticastTTL", Errno, StrError(Errno), LOG_LEVEL_WARNING);
+ }
+}
+
+
+int UdpSocket::GetMulticastTTL()
+{
+ int ttl = 0;
+ socklen_t size = sizeof(int);
+
+ if (GetSocket() == INVALID_SOCKET)
+ {
+ CreateConnection();
+ }
+ if (getsockopt(GetSocket(), SOL_IP, IP_MULTICAST_TTL, (char *)&ttl, &size) == -1)
+ {
+ Handler().LogError(this, "GetMulticastTTL", Errno, StrError(Errno), LOG_LEVEL_WARNING);
+ }
+ return ttl;
+}
+
+
+void UdpSocket::SetMulticastLoop(bool x)
+{
+ if (GetSocket() == INVALID_SOCKET)
+ {
+ CreateConnection();
+ }
+#ifdef ENABLE_IPV6
+#ifdef IPPROTO_IPV6
+ if (IsIpv6())
+ {
+ int val = x ? 1 : 0;
+ if (setsockopt(GetSocket(), IPPROTO_IPV6, IPV6_MULTICAST_LOOP, (char *)&val, sizeof(int)) == -1)
+ {
+ Handler().LogError(this, "SetMulticastLoop", Errno, StrError(Errno), LOG_LEVEL_WARNING);
+ }
+ return;
+ }
+#endif
+#endif
+ int val = x ? 1 : 0;
+ if (setsockopt(GetSocket(), SOL_IP, IP_MULTICAST_LOOP, (char *)&val, sizeof(int)) == -1)
+ {
+ Handler().LogError(this, "SetMulticastLoop", Errno, StrError(Errno), LOG_LEVEL_WARNING);
+ }
+}
+
+
+bool UdpSocket::IsMulticastLoop()
+{
+ if (GetSocket() == INVALID_SOCKET)
+ {
+ CreateConnection();
+ }
+#ifdef ENABLE_IPV6
+#ifdef IPPROTO_IPV6
+ if (IsIpv6())
+ {
+ int is_loop = 0;
+ socklen_t size = sizeof(int);
+ if (getsockopt(GetSocket(), IPPROTO_IPV6, IPV6_MULTICAST_LOOP, (char *)&is_loop, &size) == -1)
+ {
+ Handler().LogError(this, "IsMulticastLoop", Errno, StrError(Errno), LOG_LEVEL_WARNING);
+ }
+ return is_loop ? true : false;
+ }
+#endif
+#endif
+ int is_loop = 0;
+ socklen_t size = sizeof(int);
+ if (getsockopt(GetSocket(), SOL_IP, IP_MULTICAST_LOOP, (char *)&is_loop, &size) == -1)
+ {
+ Handler().LogError(this, "IsMulticastLoop", Errno, StrError(Errno), LOG_LEVEL_WARNING);
+ }
+ return is_loop ? true : false;
+}
+
+
+void UdpSocket::AddMulticastMembership(const std::string& group, const std::string& local_if, int if_index)
+{
+ if (GetSocket() == INVALID_SOCKET)
+ {
+ CreateConnection();
+ }
+#ifdef ENABLE_IPV6
+#ifdef IPPROTO_IPV6
+ if (IsIpv6())
+ {
+ struct ipv6_mreq x;
+ struct in6_addr addr;
+ if (Utility::u2ip( group, addr ))
+ {
+ x.ipv6mr_multiaddr = addr;
+ x.ipv6mr_interface = if_index;
+ if (setsockopt(GetSocket(), IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, (char *)&x, sizeof(struct ipv6_mreq)) == -1)
+ {
+ Handler().LogError(this, "AddMulticastMembership", Errno, StrError(Errno), LOG_LEVEL_WARNING);
+ }
+ }
+ return;
+ }
+#endif
+#endif
+ struct ip_mreq x; // ip_mreqn
+ ipaddr_t addr;
+ if (Utility::u2ip( group, addr ))
+ {
+ memcpy(&x.imr_multiaddr.s_addr, &addr, sizeof(addr));
+ Utility::u2ip( local_if, addr);
+ memcpy(&x.imr_interface.s_addr, &addr, sizeof(addr));
+// x.imr_ifindex = if_index;
+ if (setsockopt(GetSocket(), SOL_IP, IP_ADD_MEMBERSHIP, (char *)&x, sizeof(struct ip_mreq)) == -1)
+ {
+ Handler().LogError(this, "AddMulticastMembership", Errno, StrError(Errno), LOG_LEVEL_WARNING);
+ }
+ }
+}
+
+
+void UdpSocket::DropMulticastMembership(const std::string& group, const std::string& local_if, int if_index)
+{
+ if (GetSocket() == INVALID_SOCKET)
+ {
+ CreateConnection();
+ }
+#ifdef ENABLE_IPV6
+#ifdef IPPROTO_IPV6
+ if (IsIpv6())
+ {
+ struct ipv6_mreq x;
+ struct in6_addr addr;
+ if (Utility::u2ip( group, addr ))
+ {
+ x.ipv6mr_multiaddr = addr;
+ x.ipv6mr_interface = if_index;
+ if (setsockopt(GetSocket(), IPPROTO_IPV6, IPV6_DROP_MEMBERSHIP, (char *)&x, sizeof(struct ipv6_mreq)) == -1)
+ {
+ Handler().LogError(this, "DropMulticastMembership", Errno, StrError(Errno), LOG_LEVEL_WARNING);
+ }
+ }
+ return;
+ }
+#endif
+#endif
+ struct ip_mreq x; // ip_mreqn
+ ipaddr_t addr;
+ if (Utility::u2ip( group, addr ))
+ {
+ memcpy(&x.imr_multiaddr.s_addr, &addr, sizeof(addr));
+ Utility::u2ip( local_if, addr);
+ memcpy(&x.imr_interface.s_addr, &addr, sizeof(addr));
+// x.imr_ifindex = if_index;
+ if (setsockopt(GetSocket(), SOL_IP, IP_DROP_MEMBERSHIP, (char *)&x, sizeof(struct ip_mreq)) == -1)
+ {
+ Handler().LogError(this, "DropMulticastMembership", Errno, StrError(Errno), LOG_LEVEL_WARNING);
+ }
+ }
+}
+
+
+#ifdef ENABLE_IPV6
+#ifdef IPPROTO_IPV6
+void UdpSocket::SetMulticastHops(int hops)
+{
+ if (GetSocket() == INVALID_SOCKET)
+ {
+ CreateConnection();
+ }
+ if (!IsIpv6())
+ {
+ Handler().LogError(this, "SetMulticastHops", 0, "Ipv6 only", LOG_LEVEL_ERROR);
+ return;
+ }
+ if (setsockopt(GetSocket(), IPPROTO_IPV6, IPV6_MULTICAST_HOPS, (char *)&hops, sizeof(int)) == -1)
+ {
+ Handler().LogError(this, "SetMulticastHops", Errno, StrError(Errno), LOG_LEVEL_WARNING);
+ }
+}
+
+
+int UdpSocket::GetMulticastHops()
+{
+ if (GetSocket() == INVALID_SOCKET)
+ {
+ CreateConnection();
+ }
+ if (!IsIpv6())
+ {
+ Handler().LogError(this, "SetMulticastHops", 0, "Ipv6 only", LOG_LEVEL_ERROR);
+ return -1;
+ }
+ int hops = 0;
+ socklen_t size = sizeof(int);
+ if (getsockopt(GetSocket(), IPPROTO_IPV6, IPV6_MULTICAST_HOPS, (char *)&hops, &size) == -1)
+ {
+ Handler().LogError(this, "GetMulticastHops", Errno, StrError(Errno), LOG_LEVEL_WARNING);
+ }
+ return hops;
+}
+#endif // IPPROTO_IPV6
+#endif
+
+
+bool UdpSocket::IsBound()
+{
+ return m_bind_ok;
+}
+
+
+void UdpSocket::OnRawData(const char *buf, size_t len, struct sockaddr *sa, socklen_t sa_len)
+{
+}
+
+
+void UdpSocket::OnRawData(const char *buf, size_t len, struct sockaddr *sa, socklen_t sa_len, struct timeval *ts)
+{
+}
+
+
+port_t UdpSocket::GetPort()
+{
+ return m_port;
+}
+
+
+int UdpSocket::GetLastSizeWritten()
+{
+ return m_last_size_written;
+}
+
+
+void UdpSocket::SetTimestamp(bool x)
+{
+ m_b_read_ts = x;
+}
+
+
+#ifdef SOCKETS_NAMESPACE
+}
+#endif
+
+
diff --git a/Sockets/UdpSocket.h b/Sockets/UdpSocket.h
new file mode 100644
index 0000000..a456172
--- /dev/null
+++ b/Sockets/UdpSocket.h
@@ -0,0 +1,215 @@
+/** \file UdpSocket.h
+ ** \date 2004-02-13
+ ** \author grymse@alhem.net
+**/
+/*
+Copyright (C) 2004-2007 Anders Hedstrom
+
+This library is made available under the terms of the GNU GPL.
+
+If you would like to use this library in a closed-source application,
+a separate license agreement is available. For information about
+the closed-source license agreement for the C++ sockets library,
+please visit http://www.alhem.net/Sockets/license.html and/or
+email license@alhem.net.
+
+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.
+*/
+#ifndef _SOCKETS_UdpSocket_H
+#define _SOCKETS_UdpSocket_H
+
+#include "sockets-config.h"
+#include "Socket.h"
+
+#ifdef SOCKETS_NAMESPACE
+namespace SOCKETS_NAMESPACE {
+#endif
+
+/** Socket implementation for UDP.
+ \ingroup basic */
+class UdpSocket : public Socket
+{
+public:
+ /** Constructor.
+ \param h ISocketHandler reference
+ \param ibufsz Maximum size of receive message (extra bytes will be truncated)
+ \param ipv6 'true' if this is an ipv6 socket */
+ UdpSocket(ISocketHandler& h,int ibufsz = 16384,bool ipv6 = false, int retries = 0);
+ ~UdpSocket();
+
+ /** Called when incoming data has been received.
+ \param buf Pointer to data
+ \param len Length of data
+ \param sa Pointer to sockaddr struct of sender
+ \param sa_len Length of sockaddr struct */
+ virtual void OnRawData(const char *buf,size_t len,struct sockaddr *sa,socklen_t sa_len);
+
+ /** Called when incoming data has been received and read timestamp is enabled.
+ \param buf Pointer to data
+ \param len Length of data
+ \param sa Pointer to sockaddr struct of sender
+ \param sa_len Length of sockaddr struct
+ \param ts Timestamp from message */
+ virtual void OnRawData(const char *buf,size_t len,struct sockaddr *sa,socklen_t sa_len,struct timeval *ts);
+
+ /** To receive incoming data, call Bind to setup an incoming port.
+ \param port Incoming port number
+ \param range Port range to try if ports already in use
+ \return 0 if bind succeeded */
+ int Bind(port_t& port,int range = 1);
+ /** To receive data on a specific interface:port, use this.
+ \param intf Interface ip/hostname
+ \param port Port number
+ \param range Port range
+ \return 0 if bind succeeded */
+ int Bind(const std::string& intf,port_t& port,int range = 1);
+ /** To receive data on a specific interface:port, use this.
+ \param a Ip address
+ \param port Port number
+ \param range Port range
+ \return 0 if bind succeeded */
+ int Bind(ipaddr_t a,port_t& port,int range = 1);
+#ifdef ENABLE_IPV6
+#ifdef IPPROTO_IPV6
+ /** To receive data on a specific interface:port, use this.
+ \param a Ipv6 address
+ \param port Port number
+ \param range Port range
+ \return 0 if bind succeeded */
+ int Bind(in6_addr a,port_t& port,int range = 1);
+#endif
+#endif
+ /** To receive data on a specific interface:port, use this.
+ \param ad Socket address
+ \param range Port range
+ \return 0 if bind succeeded */
+ int Bind(SocketAddress& ad,int range = 1);
+
+ /** Define remote host.
+ \param l Address of remote host
+ \param port Port of remote host
+ \return true if successful */
+ bool Open(ipaddr_t l,port_t port);
+ /** Define remote host.
+ \param host Hostname
+ \param port Port number
+ \return true if successful */
+ bool Open(const std::string& host,port_t port);
+#ifdef ENABLE_IPV6
+#ifdef IPPROTO_IPV6
+ /** Define remote host.
+ \param a Address of remote host, ipv6
+ \param port Port of remote host
+ \return true if successful */
+ bool Open(struct in6_addr& a,port_t port);
+#endif
+#endif
+ /** Define remote host.
+ \param ad Socket address
+ \return true if successful */
+ bool Open(SocketAddress& ad);
+
+ /** Send to specified host */
+ void SendToBuf(const std::string& ,port_t,const char *data,int len,int flags = 0);
+ /** Send to specified address */
+ void SendToBuf(ipaddr_t,port_t,const char *data,int len,int flags = 0);
+#ifdef ENABLE_IPV6
+#ifdef IPPROTO_IPV6
+ /** Send to specified ipv6 address */
+ void SendToBuf(in6_addr,port_t,const char *data,int len,int flags = 0);
+#endif
+#endif
+ /** Send to specified socket address */
+ void SendToBuf(SocketAddress& ad,const char *data,int len,int flags = 0);
+
+ /** Send string to specified host */
+ void SendTo(const std::string&,port_t,const std::string&,int flags = 0);
+ /** Send string to specified address */
+ void SendTo(ipaddr_t,port_t,const std::string&,int flags = 0);
+#ifdef ENABLE_IPV6
+#ifdef IPPROTO_IPV6
+ /** Send string to specified ipv6 address */
+ void SendTo(in6_addr,port_t,const std::string&,int flags = 0);
+#endif
+#endif
+ /** Send string to specified socket address */
+ void SendTo(SocketAddress& ad,const std::string&,int flags = 0);
+
+ /** Send to connected address */
+ void SendBuf(const char *data,size_t,int flags = 0);
+ /** Send string to connected address. */
+ void Send(const std::string& ,int flags = 0);
+
+ /** Set broadcast */
+ void SetBroadcast(bool b = true);
+ /** Check broadcast flag.
+ \return true broadcast is enabled. */
+ bool IsBroadcast();
+
+ /** multicast */
+ void SetMulticastTTL(int ttl = 1);
+ int GetMulticastTTL();
+ void SetMulticastLoop(bool = true);
+ bool IsMulticastLoop();
+ void AddMulticastMembership(const std::string& group,const std::string& intf = "0.0.0.0",int if_index = 0);
+ void DropMulticastMembership(const std::string& group,const std::string& intf = "0.0.0.0",int if_index = 0);
+#ifdef ENABLE_IPV6
+#ifdef IPPROTO_IPV6
+ /** multicast, ipv6 only */
+ void SetMulticastHops(int = -1);
+ /** multicast, ipv6 only */
+ int GetMulticastHops();
+#endif
+#endif
+ /** Returns true if Bind succeeded. */
+ bool IsBound();
+ /** Return Bind port number */
+ port_t GetPort();
+
+ void OnOptions(int,int,int,SOCKET) {}
+
+ int GetLastSizeWritten();
+
+ /** Also read timestamp information from incoming message */
+ void SetTimestamp(bool = true);
+
+protected:
+ UdpSocket(const UdpSocket& s) : Socket(s) {}
+ void OnRead();
+#ifndef _WIN32
+ /** This method emulates socket recvfrom, but uses messages so we can get the timestamp */
+ int ReadTS(char *ioBuf, int inBufSize, struct sockaddr *from, socklen_t fromlen, struct timeval *ts);
+#endif
+
+private:
+ UdpSocket& operator=(const UdpSocket& ) { return *this; }
+ /** create before using sendto methods */
+ void CreateConnection();
+ char *m_ibuf; ///< Input buffer
+ int m_ibufsz; ///< Size of input buffer
+ bool m_bind_ok; ///< Bind completed successfully
+ port_t m_port; ///< Bind port number
+ int m_last_size_written;
+ int m_retries;
+ bool m_b_read_ts;
+};
+
+
+#ifdef SOCKETS_NAMESPACE
+}
+#endif
+
+#endif // _SOCKETS_UdpSocket_H
+
diff --git a/Sockets/Utility.cpp b/Sockets/Utility.cpp
new file mode 100644
index 0000000..a80e2a8
--- /dev/null
+++ b/Sockets/Utility.cpp
@@ -0,0 +1,953 @@
+/** \file Utility.cpp
+ ** \date 2004-02-13
+ ** \author grymse@alhem.net
+**/
+/*
+Copyright (C) 2004-2007 Anders Hedstrom
+
+This library is made available under the terms of the GNU GPL.
+
+If you would like to use this library in a closed-source application,
+a separate license agreement is available. For information about
+the closed-source license agreement for the C++ sockets library,
+please visit http://www.alhem.net/Sockets/license.html and/or
+email license@alhem.net.
+
+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.
+*/
+#include "Utility.h"
+#include "Parse.h"
+#include "Ipv4Address.h"
+#include "Ipv6Address.h"
+#include "RandomNumber.h"
+#include "Base64.h"
+#include <vector>
+#ifdef _WIN32
+#include <time.h>
+#else
+#include <netdb.h>
+#include <pthread.h>
+#endif
+#include <map>
+
+#ifdef SOCKETS_NAMESPACE
+namespace SOCKETS_NAMESPACE {
+#endif
+
+
+// statics
+std::string Utility::m_host;
+bool Utility::m_local_resolved = false;
+ipaddr_t Utility::m_ip = 0;
+std::string Utility::m_addr;
+#ifdef ENABLE_IPV6
+#ifdef IPPROTO_IPV6
+struct in6_addr Utility::m_local_ip6;
+std::string Utility::m_local_addr6;
+#endif
+#endif
+
+
+std::string Utility::base64(const std::string& str_in)
+{
+ std::string str;
+ Base64 m_b;
+ m_b.encode(str_in, str, false); // , false == do not add cr/lf
+ return str;
+}
+
+
+std::string Utility::base64d(const std::string& str_in)
+{
+ std::string str;
+ Base64 m_b;
+ m_b.decode(str_in, str);
+ return str;
+}
+
+
+std::string Utility::l2string(long l)
+{
+ std::string str;
+ char tmp[100];
+ sprintf(tmp,"%ld",l);
+ str = tmp;
+ return str;
+}
+
+
+std::string Utility::bigint2string(uint64_t l)
+{
+ std::string str;
+ uint64_t tmp = l;
+ while (tmp)
+ {
+ uint64_t a = tmp % 10;
+ str = (char)(a + 48) + str;
+ tmp /= 10;
+ }
+ if (!str.size())
+ {
+ str = "0";
+ }
+ return str;
+}
+
+
+uint64_t Utility::atoi64(const std::string& str)
+{
+ uint64_t l = 0;
+ for (size_t i = 0; i < str.size(); i++)
+ {
+ l = l * 10 + str[i] - 48;
+ }
+ return l;
+}
+
+
+unsigned int Utility::hex2unsigned(const std::string& str)
+{
+ unsigned int r = 0;
+ for (size_t i = 0; i < str.size(); i++)
+ {
+ r = r * 16 + str[i] - 48 - ((str[i] >= 'A') ? 7 : 0) - ((str[i] >= 'a') ? 32 : 0);
+ }
+ return r;
+}
+
+
+/*
+* Encode string per RFC1738 URL encoding rules
+* tnx rstaveley
+*/
+std::string Utility::rfc1738_encode(const std::string& src)
+{
+static char hex[] = "0123456789ABCDEF";
+ std::string dst;
+ for (size_t i = 0; i < src.size(); i++)
+ {
+ if (isalnum(src[i]))
+ {
+ dst += src[i];
+ }
+ else
+ if (src[i] == ' ')
+ {
+ dst += '+';
+ }
+ else
+ {
+ unsigned char c = static_cast<unsigned char>(src[i]);
+ dst += '%';
+ dst += hex[c / 16];
+ dst += hex[c % 16];
+ }
+ }
+ return dst;
+} // rfc1738_encode
+
+
+/*
+* Decode string per RFC1738 URL encoding rules
+* tnx rstaveley
+*/
+std::string Utility::rfc1738_decode(const std::string& src)
+{
+ std::string dst;
+ for (size_t i = 0; i < src.size(); i++)
+ {
+ if (src[i] == '%' && isxdigit(src[i + 1]) && isxdigit(src[i + 2]))
+ {
+ char c1 = src[++i];
+ char c2 = src[++i];
+ c1 = c1 - 48 - ((c1 >= 'A') ? 7 : 0) - ((c1 >= 'a') ? 32 : 0);
+ c2 = c2 - 48 - ((c2 >= 'A') ? 7 : 0) - ((c2 >= 'a') ? 32 : 0);
+ dst += (char)(c1 * 16 + c2);
+ }
+ else
+ if (src[i] == '+')
+ {
+ dst += ' ';
+ }
+ else
+ {
+ dst += src[i];
+ }
+ }
+ return dst;
+} // rfc1738_decode
+
+
+bool Utility::isipv4(const std::string& str)
+{
+ int dots = 0;
+ // %! ignore :port?
+ for (size_t i = 0; i < str.size(); i++)
+ {
+ if (str[i] == '.')
+ dots++;
+ else
+ if (!isdigit(str[i]))
+ return false;
+ }
+ if (dots != 3)
+ return false;
+ return true;
+}
+
+
+bool Utility::isipv6(const std::string& str)
+{
+ size_t qc = 0;
+ size_t qd = 0;
+ for (size_t i = 0; i < str.size(); i++)
+ {
+ qc += (str[i] == ':') ? 1 : 0;
+ qd += (str[i] == '.') ? 1 : 0;
+ }
+ if (qc > 7)
+ {
+ return false;
+ }
+ if (qd && qd != 3)
+ {
+ return false;
+ }
+ Parse pa(str,":.");
+ std::string tmp = pa.getword();
+ while (tmp.size())
+ {
+ if (tmp.size() > 4)
+ {
+ return false;
+ }
+ for (size_t i = 0; i < tmp.size(); i++)
+ {
+ if (tmp[i] < '0' || (tmp[i] > '9' && tmp[i] < 'A') ||
+ (tmp[i] > 'F' && tmp[i] < 'a') || tmp[i] > 'f')
+ {
+ return false;
+ }
+ }
+ //
+ tmp = pa.getword();
+ }
+ return true;
+}
+
+
+bool Utility::u2ip(const std::string& str, ipaddr_t& l)
+{
+ struct sockaddr_in sa;
+ bool r = Utility::u2ip(str, sa);
+ memcpy(&l, &sa.sin_addr, sizeof(l));
+ return r;
+}
+
+
+#ifdef ENABLE_IPV6
+#ifdef IPPROTO_IPV6
+bool Utility::u2ip(const std::string& str, struct in6_addr& l)
+{
+ struct sockaddr_in6 sa;
+ bool r = Utility::u2ip(str, sa);
+ l = sa.sin6_addr;
+ return r;
+}
+#endif
+#endif
+
+
+void Utility::l2ip(const ipaddr_t ip, std::string& str)
+{
+ struct sockaddr_in sa;
+ memset(&sa, 0, sizeof(sa));
+ sa.sin_family = AF_INET;
+ memcpy(&sa.sin_addr, &ip, sizeof(sa.sin_addr));
+ Utility::reverse( (struct sockaddr *)&sa, sizeof(sa), str, NI_NUMERICHOST);
+}
+
+
+void Utility::l2ip(const in_addr& ip, std::string& str)
+{
+ struct sockaddr_in sa;
+ memset(&sa, 0, sizeof(sa));
+ sa.sin_family = AF_INET;
+ sa.sin_addr = ip;
+ Utility::reverse( (struct sockaddr *)&sa, sizeof(sa), str, NI_NUMERICHOST);
+}
+
+
+#ifdef ENABLE_IPV6
+#ifdef IPPROTO_IPV6
+void Utility::l2ip(const struct in6_addr& ip, std::string& str,bool mixed)
+{
+ char slask[100]; // l2ip temporary
+ *slask = 0;
+ unsigned int prev = 0;
+ bool skipped = false;
+ bool ok_to_skip = true;
+ if (mixed)
+ {
+ unsigned short x;
+ unsigned short addr16[8];
+ memcpy(addr16, &ip, sizeof(addr16));
+ for (size_t i = 0; i < 6; i++)
+ {
+ x = ntohs(addr16[i]);
+ if (*slask && (x || !ok_to_skip || prev))
+ strcat(slask,":");
+ if (x || !ok_to_skip)
+ {
+ sprintf(slask + strlen(slask),"%x", x);
+ if (x && skipped)
+ ok_to_skip = false;
+ }
+ else
+ {
+ skipped = true;
+ }
+ prev = x;
+ }
+ x = ntohs(addr16[6]);
+ sprintf(slask + strlen(slask),":%u.%u",x / 256,x & 255);
+ x = ntohs(addr16[7]);
+ sprintf(slask + strlen(slask),".%u.%u",x / 256,x & 255);
+ }
+ else
+ {
+ struct sockaddr_in6 sa;
+ memset(&sa, 0, sizeof(sa));
+ sa.sin6_family = AF_INET6;
+ sa.sin6_addr = ip;
+ Utility::reverse( (struct sockaddr *)&sa, sizeof(sa), str, NI_NUMERICHOST);
+ return;
+ }
+ str = slask;
+}
+
+
+int Utility::in6_addr_compare(in6_addr a,in6_addr b)
+{
+ for (size_t i = 0; i < 16; i++)
+ {
+ if (a.s6_addr[i] < b.s6_addr[i])
+ return -1;
+ if (a.s6_addr[i] > b.s6_addr[i])
+ return 1;
+ }
+ return 0;
+}
+#endif
+#endif
+
+
+void Utility::ResolveLocal()
+{
+ char h[256];
+
+ // get local hostname and translate into ip-address
+ *h = 0;
+ gethostname(h,255);
+ {
+ if (Utility::u2ip(h, m_ip))
+ {
+ Utility::l2ip(m_ip, m_addr);
+ }
+ }
+#ifdef ENABLE_IPV6
+#ifdef IPPROTO_IPV6
+ memset(&m_local_ip6, 0, sizeof(m_local_ip6));
+ {
+ if (Utility::u2ip(h, m_local_ip6))
+ {
+ Utility::l2ip(m_local_ip6, m_local_addr6);
+ }
+ }
+#endif
+#endif
+ m_host = h;
+ m_local_resolved = true;
+}
+
+
+const std::string& Utility::GetLocalHostname()
+{
+ if (!m_local_resolved)
+ {
+ ResolveLocal();
+ }
+ return m_host;
+}
+
+
+ipaddr_t Utility::GetLocalIP()
+{
+ if (!m_local_resolved)
+ {
+ ResolveLocal();
+ }
+ return m_ip;
+}
+
+
+const std::string& Utility::GetLocalAddress()
+{
+ if (!m_local_resolved)
+ {
+ ResolveLocal();
+ }
+ return m_addr;
+}
+
+
+#ifdef ENABLE_IPV6
+#ifdef IPPROTO_IPV6
+const struct in6_addr& Utility::GetLocalIP6()
+{
+ if (!m_local_resolved)
+ {
+ ResolveLocal();
+ }
+ return m_local_ip6;
+}
+
+
+const std::string& Utility::GetLocalAddress6()
+{
+ if (!m_local_resolved)
+ {
+ ResolveLocal();
+ }
+ return m_local_addr6;
+}
+#endif
+#endif
+
+
+void Utility::SetEnv(const std::string& var,const std::string& value)
+{
+#if (defined(SOLARIS8) || defined(SOLARIS))
+ {
+ static std::map<std::string, char *> vmap;
+ if (vmap.find(var) != vmap.end())
+ {
+ delete[] vmap[var];
+ }
+ vmap[var] = new char[var.size() + 1 + value.size() + 1];
+ sprintf(vmap[var], "%s=%s", var.c_str(), value.c_str());
+ putenv( vmap[var] );
+ }
+#elif defined _WIN32
+ {
+ std::string slask = var + "=" + value;
+ _putenv( (char *)slask.c_str());
+ }
+#else
+ setenv(var.c_str(), value.c_str(), 1);
+#endif
+}
+
+
+std::string Utility::Sa2String(struct sockaddr *sa)
+{
+#ifdef ENABLE_IPV6
+#ifdef IPPROTO_IPV6
+ if (sa -> sa_family == AF_INET6)
+ {
+ struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)sa;
+ std::string tmp;
+ Utility::l2ip(sa6 -> sin6_addr, tmp);
+ return tmp + ":" + Utility::l2string(ntohs(sa6 -> sin6_port));
+ }
+#endif
+#endif
+ if (sa -> sa_family == AF_INET)
+ {
+ struct sockaddr_in *sa4 = (struct sockaddr_in *)sa;
+ ipaddr_t a;
+ memcpy(&a, &sa4 -> sin_addr, 4);
+ std::string tmp;
+ Utility::l2ip(a, tmp);
+ return tmp + ":" + Utility::l2string(ntohs(sa4 -> sin_port));
+ }
+ return "";
+}
+
+
+void Utility::GetTime(struct timeval *p)
+{
+#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; // make it usecs
+ p->tv_sec = (long)tt / 1000000;
+ p->tv_usec = (long)tt % 1000000;
+#else
+ gettimeofday(p, NULL);
+#endif
+}
+
+
+std::auto_ptr<SocketAddress> Utility::CreateAddress(struct sockaddr *sa,socklen_t sa_len)
+{
+ switch (sa -> sa_family)
+ {
+ case AF_INET:
+ if (sa_len == sizeof(struct sockaddr_in))
+ {
+ struct sockaddr_in *p = (struct sockaddr_in *)sa;
+ return std::auto_ptr<SocketAddress>(new Ipv4Address(*p));
+ }
+ break;
+#ifdef ENABLE_IPV6
+#ifdef IPPROTO_IPV6
+ case AF_INET6:
+ if (sa_len == sizeof(struct sockaddr_in6))
+ {
+ struct sockaddr_in6 *p = (struct sockaddr_in6 *)sa;
+ return std::auto_ptr<SocketAddress>(new Ipv6Address(*p));
+ }
+ break;
+#endif
+#endif
+ }
+ return std::auto_ptr<SocketAddress>(NULL);
+}
+
+
+bool Utility::u2ip(const std::string& host, struct sockaddr_in& sa, int ai_flags)
+{
+ memset(&sa, 0, sizeof(sa));
+ sa.sin_family = AF_INET;
+#ifdef NO_GETADDRINFO
+ if ((ai_flags & AI_NUMERICHOST) != 0 || isipv4(host))
+ {
+ Parse pa((char *)host.c_str(), ".");
+ union {
+ struct {
+ unsigned char b1;
+ unsigned char b2;
+ unsigned char b3;
+ unsigned char b4;
+ } a;
+ ipaddr_t l;
+ } u;
+ u.a.b1 = static_cast<unsigned char>(pa.getvalue());
+ u.a.b2 = static_cast<unsigned char>(pa.getvalue());
+ u.a.b3 = static_cast<unsigned char>(pa.getvalue());
+ u.a.b4 = static_cast<unsigned char>(pa.getvalue());
+ memcpy(&sa.sin_addr, &u.l, sizeof(sa.sin_addr));
+ return true;
+ }
+#ifndef LINUX
+ struct hostent *he = gethostbyname( host.c_str() );
+ if (!he)
+ {
+ return false;
+ }
+ memcpy(&sa.sin_addr, he -> h_addr, sizeof(sa.sin_addr));
+#else
+ struct hostent he;
+ struct hostent *result = NULL;
+ int myerrno = 0;
+ char buf[2000];
+ int n = gethostbyname_r(host.c_str(), &he, buf, sizeof(buf), &result, &myerrno);
+ if (n || !result)
+ {
+ return false;
+ }
+ if (he.h_addr_list && he.h_addr_list[0])
+ memcpy(&sa.sin_addr, he.h_addr, 4);
+ else
+ return false;
+#endif
+ return true;
+#else
+ struct addrinfo hints;
+ memset(&hints, 0, sizeof(hints));
+ // AI_NUMERICHOST
+ // AI_CANONNAME
+ // AI_PASSIVE - server
+ // AI_ADDRCONFIG
+ // AI_V4MAPPED
+ // AI_ALL
+ // AI_NUMERICSERV
+ hints.ai_flags = ai_flags;
+ hints.ai_family = AF_INET;
+ hints.ai_socktype = 0;
+ hints.ai_protocol = 0;
+ struct addrinfo *res;
+ if (Utility::isipv4(host))
+ hints.ai_flags |= AI_NUMERICHOST;
+ int n = getaddrinfo(host.c_str(), NULL, &hints, &res);
+ if (!n)
+ {
+ static RandomNumber prng( true );
+ std::vector<struct addrinfo *> vec;
+ struct addrinfo *ai = res;
+ while (ai)
+ {
+ if (ai -> ai_addrlen == sizeof(sa))
+ vec.push_back( ai );
+ prng.next();
+ //
+ ai = ai -> ai_next;
+ }
+ if (!vec.size())
+ return false;
+ ai = vec[prng.next() % vec.size()];
+ {
+ memcpy(&sa, ai -> ai_addr, ai -> ai_addrlen);
+ }
+ freeaddrinfo(res);
+ return true;
+ }
+ std::string error = "Error: ";
+#ifndef __CYGWIN__
+ error += gai_strerror(n);
+#endif
+ return false;
+#endif // NO_GETADDRINFO
+}
+
+
+#ifdef ENABLE_IPV6
+#ifdef IPPROTO_IPV6
+bool Utility::u2ip(const std::string& host, struct sockaddr_in6& sa, int ai_flags)
+{
+ memset(&sa, 0, sizeof(sa));
+ sa.sin6_family = AF_INET6;
+#ifdef NO_GETADDRINFO
+ if ((ai_flags & AI_NUMERICHOST) != 0 || isipv6(host))
+ {
+ std::list<std::string> vec;
+ size_t x = 0;
+ for (size_t i = 0; i <= host.size(); i++)
+ {
+ if (i == host.size() || host[i] == ':')
+ {
+ std::string s = host.substr(x, i - x);
+ //
+ if (strstr(s.c_str(),".")) // x.x.x.x
+ {
+ Parse pa(s,".");
+ char slask[100]; // u2ip temporary hex2string conversion
+ unsigned long b0 = static_cast<unsigned long>(pa.getvalue());
+ unsigned long b1 = static_cast<unsigned long>(pa.getvalue());
+ unsigned long b2 = static_cast<unsigned long>(pa.getvalue());
+ unsigned long b3 = static_cast<unsigned long>(pa.getvalue());
+ sprintf(slask,"%lx",b0 * 256 + b1);
+ vec.push_back(slask);
+ sprintf(slask,"%lx",b2 * 256 + b3);
+ vec.push_back(slask);
+ }
+ else
+ {
+ vec.push_back(s);
+ }
+ //
+ x = i + 1;
+ }
+ }
+ size_t sz = vec.size(); // number of byte pairs
+ size_t i = 0; // index in in6_addr.in6_u.u6_addr16[] ( 0 .. 7 )
+ unsigned short addr16[8];
+ for (std::list<std::string>::iterator it = vec.begin(); it != vec.end(); it++)
+ {
+ std::string bytepair = *it;
+ if (bytepair.size())
+ {
+ addr16[i++] = htons(Utility::hex2unsigned(bytepair));
+ }
+ else
+ {
+ addr16[i++] = 0;
+ while (sz++ < 8)
+ {
+ addr16[i++] = 0;
+ }
+ }
+ }
+ memcpy(&sa.sin6_addr, addr16, sizeof(addr16));
+ return true;
+ }
+#ifdef SOLARIS
+ int errnum = 0;
+ struct hostent *he = getipnodebyname( host.c_str(), AF_INET6, 0, &errnum );
+#else
+ struct hostent *he = gethostbyname2( host.c_str(), AF_INET6 );
+#endif
+ if (!he)
+ {
+ return false;
+ }
+ memcpy(&sa.sin6_addr,he -> h_addr_list[0],he -> h_length);
+#ifdef SOLARIS
+ free(he);
+#endif
+ return true;
+#else
+ struct addrinfo hints;
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_flags = ai_flags;
+ hints.ai_family = AF_INET6;
+ hints.ai_socktype = 0;
+ hints.ai_protocol = 0;
+ struct addrinfo *res;
+ if (Utility::isipv6(host))
+ hints.ai_flags |= AI_NUMERICHOST;
+ int n = getaddrinfo(host.c_str(), NULL, &hints, &res);
+ if (!n)
+ {
+ static RandomNumber prng( true );
+ std::vector<struct addrinfo *> vec;
+ struct addrinfo *ai = res;
+ while (ai)
+ {
+ if (ai -> ai_addrlen == sizeof(sa))
+ vec.push_back( ai );
+ prng.next();
+ //
+ ai = ai -> ai_next;
+ }
+ if (!vec.size())
+ return false;
+ ai = vec[prng.next() % vec.size()];
+ {
+ memcpy(&sa, ai -> ai_addr, ai -> ai_addrlen);
+ }
+ freeaddrinfo(res);
+ return true;
+ }
+ std::string error = "Error: ";
+#ifndef __CYGWIN__
+ error += gai_strerror(n);
+#endif
+ return false;
+#endif // NO_GETADDRINFO
+}
+#endif // IPPROTO_IPV6
+#endif // ENABLE_IPV6
+
+
+bool Utility::reverse(struct sockaddr *sa, socklen_t sa_len, std::string& hostname, int flags)
+{
+ std::string service;
+ return Utility::reverse(sa, sa_len, hostname, service, flags);
+}
+
+
+bool Utility::reverse(struct sockaddr *sa, socklen_t sa_len, std::string& hostname, std::string& service, int flags)
+{
+ hostname = "";
+ service = "";
+#ifdef NO_GETADDRINFO
+ switch (sa -> sa_family)
+ {
+ case AF_INET:
+ if (flags & NI_NUMERICHOST)
+ {
+ union {
+ struct {
+ unsigned char b1;
+ unsigned char b2;
+ unsigned char b3;
+ unsigned char b4;
+ } a;
+ ipaddr_t l;
+ } u;
+ struct sockaddr_in *sa_in = (struct sockaddr_in *)sa;
+ memcpy(&u.l, &sa_in -> sin_addr, sizeof(u.l));
+ char tmp[100];
+ sprintf(tmp, "%u.%u.%u.%u", u.a.b1, u.a.b2, u.a.b3, u.a.b4);
+ hostname = tmp;
+ return true;
+ }
+ else
+ {
+ struct sockaddr_in *sa_in = (struct sockaddr_in *)sa;
+ struct hostent *h = gethostbyaddr( (const char *)&sa_in -> sin_addr, sizeof(sa_in -> sin_addr), AF_INET);
+ if (h)
+ {
+ hostname = h -> h_name;
+ return true;
+ }
+ }
+ break;
+#ifdef ENABLE_IPV6
+ case AF_INET6:
+ if (flags & NI_NUMERICHOST)
+ {
+ char slask[100]; // l2ip temporary
+ *slask = 0;
+ unsigned int prev = 0;
+ bool skipped = false;
+ bool ok_to_skip = true;
+ {
+ unsigned short addr16[8];
+ struct sockaddr_in6 *sa_in6 = (struct sockaddr_in6 *)sa;
+ memcpy(addr16, &sa_in6 -> sin6_addr, sizeof(addr16));
+ for (size_t i = 0; i < 8; i++)
+ {
+ unsigned short x = ntohs(addr16[i]);
+ if (*slask && (x || !ok_to_skip || prev))
+ strcat(slask,":");
+ if (x || !ok_to_skip)
+ {
+ sprintf(slask + strlen(slask),"%x", x);
+ if (x && skipped)
+ ok_to_skip = false;
+ }
+ else
+ {
+ skipped = true;
+ }
+ prev = x;
+ }
+ }
+ if (!*slask)
+ strcpy(slask, "::");
+ hostname = slask;
+ return true;
+ }
+ else
+ {
+ // %! TODO: ipv6 reverse lookup
+ struct sockaddr_in6 *sa_in = (struct sockaddr_in6 *)sa;
+ struct hostent *h = gethostbyaddr( (const char *)&sa_in -> sin6_addr, sizeof(sa_in -> sin6_addr), AF_INET6);
+ if (h)
+ {
+ hostname = h -> h_name;
+ return true;
+ }
+ }
+ break;
+#endif
+ }
+ return false;
+#else
+ char host[NI_MAXHOST];
+ char serv[NI_MAXSERV];
+ // NI_NOFQDN
+ // NI_NUMERICHOST
+ // NI_NAMEREQD
+ // NI_NUMERICSERV
+ // NI_DGRAM
+ int n = getnameinfo(sa, sa_len, host, sizeof(host), serv, sizeof(serv), flags);
+ if (n)
+ {
+ // EAI_AGAIN
+ // EAI_BADFLAGS
+ // EAI_FAIL
+ // EAI_FAMILY
+ // EAI_MEMORY
+ // EAI_NONAME
+ // EAI_OVERFLOW
+ // EAI_SYSTEM
+ return false;
+ }
+ hostname = host;
+ service = serv;
+ return true;
+#endif // NO_GETADDRINFO
+}
+
+
+bool Utility::u2service(const std::string& name, int& service, int ai_flags)
+{
+#ifdef NO_GETADDRINFO
+ // %!
+ return false;
+#else
+ struct addrinfo hints;
+ service = 0;
+ memset(&hints, 0, sizeof(hints));
+ // AI_NUMERICHOST
+ // AI_CANONNAME
+ // AI_PASSIVE - server
+ // AI_ADDRCONFIG
+ // AI_V4MAPPED
+ // AI_ALL
+ // AI_NUMERICSERV
+ hints.ai_flags = ai_flags;
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = 0;
+ hints.ai_protocol = 0;
+ struct addrinfo *res;
+ int n = getaddrinfo(NULL, name.c_str(), &hints, &res);
+ if (!n)
+ {
+ service = res -> ai_protocol;
+ freeaddrinfo(res);
+ return true;
+ }
+ return false;
+#endif // NO_GETADDRINFO
+}
+
+
+unsigned long Utility::ThreadID()
+{
+#ifdef _WIN32
+ return GetCurrentThreadId();
+#else
+ return (unsigned long)pthread_self();
+#endif
+}
+
+
+std::string Utility::ToLower(const std::string& str)
+{
+ std::string r;
+ for (size_t i = 0; i < str.size(); i++)
+ {
+ if (str[i] >= 'A' && str[i] <= 'Z')
+ r += str[i] | 32;
+ else
+ r += str[i];
+ }
+ return r;
+}
+
+
+std::string Utility::ToUpper(const std::string& str)
+{
+ std::string r;
+ for (size_t i = 0; i < str.size(); i++)
+ {
+ if (str[i] >= 'a' && str[i] <= 'z')
+ r += (char)(str[i] - 32);
+ else
+ r += str[i];
+ }
+ return r;
+}
+
+
+std::string Utility::ToString(double d)
+{
+ char tmp[100];
+ sprintf(tmp, "%f", d);
+ return tmp;
+}
+
+
+#ifdef SOCKETS_NAMESPACE
+}
+#endif
+
diff --git a/Sockets/Utility.h b/Sockets/Utility.h
new file mode 100644
index 0000000..133fbd1
--- /dev/null
+++ b/Sockets/Utility.h
@@ -0,0 +1,153 @@
+/** \file Utility.h
+ ** \date 2004-02-13
+ ** \author grymse@alhem.net
+**/
+/*
+Copyright (C) 2004-2007 Anders Hedstrom
+
+This library is made available under the terms of the GNU GPL.
+
+If you would like to use this library in a closed-source application,
+a separate license agreement is available. For information about
+the closed-source license agreement for the C++ sockets library,
+please visit http://www.alhem.net/Sockets/license.html and/or
+email license@alhem.net.
+
+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.
+*/
+#ifndef _SOCKETS_Utility_H
+#define _SOCKETS_Utility_H
+
+#include "sockets-config.h"
+#include <ctype.h>
+#include <memory>
+#include "socket_include.h"
+
+#ifdef SOCKETS_NAMESPACE
+namespace SOCKETS_NAMESPACE {
+#endif
+
+class SocketAddress;
+
+/** Conversion utilities.
+ \ingroup util */
+class Utility
+{
+public:
+ static std::string base64(const std::string& str_in);
+ static std::string base64d(const std::string& str_in);
+ static std::string l2string(long l);
+ static std::string bigint2string(uint64_t l);
+ static uint64_t atoi64(const std::string& str);
+ static unsigned int hex2unsigned(const std::string& str);
+ static std::string rfc1738_encode(const std::string& src);
+ static std::string rfc1738_decode(const std::string& src);
+
+ /** Checks whether a string is a valid ipv4/ipv6 ip number. */
+ static bool isipv4(const std::string&);
+ /** Checks whether a string is a valid ipv4/ipv6 ip number. */
+ static bool isipv6(const std::string&);
+
+ /** Hostname to ip resolution ipv4, not asynchronous. */
+ static bool u2ip(const std::string&, ipaddr_t&);
+ static bool u2ip(const std::string&, struct sockaddr_in& sa, int ai_flags = 0);
+
+#ifdef ENABLE_IPV6
+#ifdef IPPROTO_IPV6
+ /** Hostname to ip resolution ipv6, not asynchronous. */
+ static bool u2ip(const std::string&, struct in6_addr&);
+ static bool u2ip(const std::string&, struct sockaddr_in6& sa, int ai_flags = 0);
+#endif
+#endif
+
+ /** Reverse lookup of address to hostname */
+ static bool reverse(struct sockaddr *sa, socklen_t sa_len, std::string&, int flags = 0);
+ static bool reverse(struct sockaddr *sa, socklen_t sa_len, std::string& hostname, std::string& service, int flags = 0);
+
+ static bool u2service(const std::string& name, int& service, int ai_flags = 0);
+
+ /** Convert binary ip address to string: ipv4. */
+ static void l2ip(const ipaddr_t,std::string& );
+ static void l2ip(const in_addr&,std::string& );
+#ifdef ENABLE_IPV6
+#ifdef IPPROTO_IPV6
+ /** Convert binary ip address to string: ipv6. */
+ static void l2ip(const struct in6_addr&,std::string& ,bool mixed = false);
+
+ /** ipv6 address compare. */
+ static int in6_addr_compare(in6_addr,in6_addr);
+#endif
+#endif
+ /** ResolveLocal (hostname) - call once before calling any GetLocal method. */
+ static void ResolveLocal();
+ /** Returns local hostname, ResolveLocal must be called once before using.
+ \sa ResolveLocal */
+ static const std::string& GetLocalHostname();
+ /** Returns local ip, ResolveLocal must be called once before using.
+ \sa ResolveLocal */
+ static ipaddr_t GetLocalIP();
+ /** Returns local ip number as string.
+ \sa ResolveLocal */
+ static const std::string& GetLocalAddress();
+#ifdef ENABLE_IPV6
+#ifdef IPPROTO_IPV6
+ /** Returns local ipv6 ip.
+ \sa ResolveLocal */
+ static const struct in6_addr& GetLocalIP6();
+ /** Returns local ipv6 address.
+ \sa ResolveLocal */
+ static const std::string& GetLocalAddress6();
+#endif
+#endif
+ /** Set environment variable.
+ \param var Name of variable to set
+ \param value Value */
+ static void SetEnv(const std::string& var,const std::string& value);
+ /** Convert sockaddr struct to human readable string.
+ \param sa Ptr to sockaddr struct */
+ static std::string Sa2String(struct sockaddr *sa);
+
+ /** Get current time in sec/microseconds. */
+ static void GetTime(struct timeval *);
+
+ static std::auto_ptr<SocketAddress> CreateAddress(struct sockaddr *,socklen_t);
+
+ static unsigned long ThreadID();
+
+ static std::string ToLower(const std::string& str);
+ static std::string ToUpper(const std::string& str);
+
+ static std::string ToString(double d);
+
+private:
+ static std::string m_host; ///< local hostname
+ static ipaddr_t m_ip; ///< local ip address
+ static std::string m_addr; ///< local ip address in string format
+#ifdef ENABLE_IPV6
+#ifdef IPPROTO_IPV6
+ static struct in6_addr m_local_ip6; ///< local ipv6 address
+#endif
+ static std::string m_local_addr6; ///< local ipv6 address in string format
+#endif
+ static bool m_local_resolved; ///< ResolveLocal has been called if true
+};
+
+
+#ifdef SOCKETS_NAMESPACE
+}
+#endif
+
+#endif // _SOCKETS_Utility_H
+
diff --git a/Sockets/ajp13.h b/Sockets/ajp13.h
new file mode 100644
index 0000000..b82f45d
--- /dev/null
+++ b/Sockets/ajp13.h
@@ -0,0 +1,91 @@
+/**
+ ** \file ajp13.h
+ ** \date 2007-10-05
+ ** \author grymse@alhem.net
+**/
+/*
+Copyright (C) 2007 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.
+*/
+#ifndef _SOCKETS_Ajp13_H
+#define _SOCKETS_Ajp13_H
+
+#ifdef SOCKETS_NAMESPACE
+namespace SOCKETS_NAMESPACE {
+#endif
+
+#define HTTP_REQUEST_ACCEPT 0xa001
+#define HTTP_REQUEST_ACCEPT_CHARSET 0xa002
+#define HTTP_REQUEST_ACCEPT_ENCODING 0xa003
+#define HTTP_REQUEST_ACCEPT_LANGUAGE 0xa004
+#define HTTP_REQUEST_AUTHORIZATION 0xa005
+#define HTTP_REQUEST_CONNECTION 0xa006
+#define HTTP_REQUEST_CONTENT_TYPE 0xa007
+#define HTTP_REQUEST_CONTENT_LENGTH 0xa008
+#define HTTP_REQUEST_COOKIE 0xa009
+#define HTTP_REQUEST_COOKIE2 0xa00a
+#define HTTP_REQUEST_HOST 0xa00b
+#define HTTP_REQUEST_PRAGMA 0xa00c
+#define HTTP_REQUEST_REFERER 0xa00d
+#define HTTP_REQUEST_USER_AGENT 0xa00e
+
+#define HTTP_METHOD_OPTIONS 1
+#define HTTP_METHOD_GET 2
+#define HTTP_METHOD_HEAD 3
+#define HTTP_METHOD_POST 4
+#define HTTP_METHOD_PUT 5
+#define HTTP_METHOD_DELETE 6
+#define HTTP_METHOD_TRACE 7
+#define HTTP_METHOD_PROPFIND 8
+#define HTTP_METHOD_PROPPATCH 9
+#define HTTP_METHOD_MKCOL 10
+#define HTTP_METHOD_COPY 11
+#define HTTP_METHOD_MOVE 12
+#define HTTP_METHOD_LOCK 13
+#define HTTP_METHOD_UNLOCK 14
+#define HTTP_METHOD_ACL 15
+#define HTTP_METHOD_REPORT 16
+#define HTTP_METHOD_VERSION_CONTROL 17 // with a dash "VERSION-CONTROL"
+#define HTTP_METHOD_CHECKIN 18
+#define HTTP_METHOD_CHECKOUT 19
+#define HTTP_METHOD_UNCHECKOUT 20
+#define HTTP_METHOD_SEARCH 21
+#define HTTP_METHOD_MKWORKSPACE 22
+#define HTTP_METHOD_UPDATE 23
+#define HTTP_METHOD_LABEL 24
+#define HTTP_METHOD_MERGE 25
+#define HTTP_METHOD_BASELINE_CONTROL 26
+#define HTTP_METHOD_MKACTIVITY 27
+
+#define ATTR_CONTEXT 1
+#define ATTR_SERVLET_PATH 2
+#define ATTR_REMOTE_USER 3
+#define ATTR_AUTH_TYPE 4
+#define ATTR_QUERY_STRING 5
+#define ATTR_ROUTE 6
+#define ATTR_SSL_CERT 7
+#define ATTR_SSL_CIPHER 8
+#define ATTR_SSL_SESSION 9
+#define ATTR_SSL_KEY_SIZE 11
+#define ATTR_SECRET 12
+#define ATTR_STORED_METHOD 13
+
+#ifdef SOCKETS_NAMESPACE
+} // namespace SOCKETS_NAMESPACE {
+#endif
+
+#endif // _SOCKETS_Ajp13_H
+
diff --git a/Sockets/gpl.txt b/Sockets/gpl.txt
new file mode 100644
index 0000000..5b6e7c6
--- /dev/null
+++ b/Sockets/gpl.txt
@@ -0,0 +1,340 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ 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
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/Sockets/mkdot.sh b/Sockets/mkdot.sh
new file mode 100755
index 0000000..598de96
--- /dev/null
+++ b/Sockets/mkdot.sh
@@ -0,0 +1,13 @@
+#!/bin/sh
+PROJECT_DIR=/usr/local/apache/www.alhem.net/htdocs/Sockets
+PROJECT_NAME=sockets
+/usr/local/bin/dp \
+ -D_RUN_DP \
+ -DUSE_SCTP -D_THREADSAFE_SOCKETS \
+ -DHAVE_OPENSSL -DENABLE_POOL -DENABLE_RECONNECT -DENABLE_SOCKS4 \
+ -DENABLE_IPV6 -DENABLE_DETACH -DENABLE_RESOLVER -DENABLE_TRIGGERS \
+ -fontsize 12 \
+ -lr -dot -cluster | grep -v std > x.dot
+dot -Tpng -o $PROJECT_DIR/sockets.png x.dot
+dot -Tcmapx -o $PROJECT_DIR/sockets.cmap x.dot
+/usr/local/bin/mkjs $PROJECT_DIR/$PROJECT_NAME.cmap > $PROJECT_DIR/$PROJECT_NAME.js
diff --git a/Sockets/socket_include.cpp b/Sockets/socket_include.cpp
new file mode 100644
index 0000000..07b986b
--- /dev/null
+++ b/Sockets/socket_include.cpp
@@ -0,0 +1,90 @@
+/** \file socket_include.cpp
+ ** \date 2004-11-28
+ ** \author grymse@alhem.net
+**/
+/*
+Copyright (C) 2004-2007 Anders Hedstrom
+
+This library is made available under the terms of the GNU GPL.
+
+If you would like to use this library in a closed-source application,
+a separate license agreement is available. For information about
+the closed-source license agreement for the C++ sockets library,
+please visit http://www.alhem.net/Sockets/license.html and/or
+email license@alhem.net.
+
+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.
+*/
+#include <stdio.h>
+
+// only to be included in win32 projects
+const char *StrError(int x)
+{
+static char tmp[100];
+ switch (x)
+ {
+ case 10004: return "Interrupted function call.";
+ case 10013: return "Permission denied.";
+ case 10014: return "Bad address.";
+ case 10022: return "Invalid argument.";
+ case 10024: return "Too many open files.";
+ case 10035: return "Resource temporarily unavailable.";
+ case 10036: return "Operation now in progress.";
+ case 10037: return "Operation already in progress.";
+ case 10038: return "Socket operation on nonsocket.";
+ case 10039: return "Destination address required.";
+ case 10040: return "Message too long.";
+ case 10041: return "Protocol wrong type for socket.";
+ case 10042: return "Bad protocol option.";
+ case 10043: return "Protocol not supported.";
+ case 10044: return "Socket type not supported.";
+ case 10045: return "Operation not supported.";
+ case 10046: return "Protocol family not supported.";
+ case 10047: return "Address family not supported by protocol family.";
+ case 10048: return "Address already in use.";
+ case 10049: return "Cannot assign requested address.";
+ case 10050: return "Network is down.";
+ case 10051: return "Network is unreachable.";
+ case 10052: return "Network dropped connection on reset.";
+ case 10053: return "Software caused connection abort.";
+ case 10054: return "Connection reset by peer.";
+ case 10055: return "No buffer space available.";
+ case 10056: return "Socket is already connected.";
+ case 10057: return "Socket is not connected.";
+ case 10058: return "Cannot send after socket shutdown.";
+ case 10060: return "Connection timed out.";
+ case 10061: return "Connection refused.";
+ case 10064: return "Host is down.";
+ case 10065: return "No route to host.";
+ case 10067: return "Too many processes.";
+ case 10091: return "Network subsystem is unavailable.";
+ case 10092: return "Winsock.dll version out of range.";
+ case 10093: return "Successful WSAStartup not yet performed.";
+ case 10101: return "Graceful shutdown in progress.";
+ case 10109: return "Class type not found.";
+ case 11001: return "Host not found.";
+ case 11002: return "Nonauthoritative host not found.";
+ case 11003: return "This is a nonrecoverable error.";
+ case 11004: return "Valid name, no data record of requested type.";
+
+ default:
+ break;
+ }
+ sprintf(tmp, "Winsock error code: %d", x);
+ return tmp;
+}
+
+
+
diff --git a/Sockets/socket_include.h b/Sockets/socket_include.h
new file mode 100644
index 0000000..213c8b3
--- /dev/null
+++ b/Sockets/socket_include.h
@@ -0,0 +1,288 @@
+/** \file socket_include.h
+ ** \date 2005-04-12
+ ** \author grymse@alhem.net
+**/
+/*
+Copyright (C) 2004-2007 Anders Hedstrom
+
+This library is made available under the terms of the GNU GPL.
+
+If you would like to use this library in a closed-source application,
+a separate license agreement is available. For information about
+the closed-source license agreement for the C++ sockets library,
+please visit http://www.alhem.net/Sockets/license.html and/or
+email license@alhem.net.
+
+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.
+*/
+#ifndef _SOCKETS_socket_include_H
+#define _SOCKETS_socket_include_H
+#include "sockets-config.h"
+
+#ifdef _MSC_VER
+#pragma warning(disable:4514)
+#endif
+
+// common defines affecting library and applications using library
+
+/* Define SOCKETS_DYNAMIC_TEMP to use dynamically allocated buffers
+ in read operations - helps on ECOS */
+#define SOCKETS_DYNAMIC_TEMP
+
+
+// platform specific stuff
+#if (defined(__unix__) || defined(unix)) && !defined(USG)
+#include <sys/param.h>
+#endif
+#include <list>
+
+// int64
+#ifdef _WIN32
+typedef unsigned __int64 uint64_t;
+#else
+#include <stdlib.h>
+#ifdef SOLARIS
+# include <sys/types.h>
+#else
+# include <stdint.h>
+#endif
+#endif
+
+#ifndef _WIN32
+// ----------------------------------------
+// common unix includes / defines
+#include <unistd.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+//#include <netdb.h>
+
+// all typedefs in this file will be declared outside the sockets namespace,
+// because some os's will already have one or more of the type defined.
+typedef int SOCKET;
+#define Errno errno
+#define StrError strerror
+
+#ifdef SOCKETS_NAMESPACE
+namespace SOCKETS_NAMESPACE {
+#endif
+
+
+// WIN32 adapt
+#define closesocket close
+#define INVALID_SOCKET -1
+#define SOCKET_ERROR -1
+
+#ifndef INADDR_NONE
+#define INADDR_NONE ((unsigned long) -1)
+#endif // INADDR_NONE
+
+#ifdef SOCKETS_NAMESPACE
+}
+#endif
+
+#endif // !_WIN32
+
+
+// ----------------------------------------
+// Generic
+#ifndef SOL_IP
+#define SOL_IP IPPROTO_IP
+#endif
+
+
+// ----------------------------------------
+// OS specific adaptions
+
+#ifdef SOLARIS
+// ----------------------------------------
+// Solaris
+typedef unsigned short port_t;
+#ifdef SOCKETS_NAMESPACE
+namespace SOCKETS_NAMESPACE {
+#endif
+// no defs
+
+#ifdef SOCKETS_NAMESPACE
+}
+#endif
+
+#define s6_addr16 _S6_un._S6_u8
+#define MSG_NOSIGNAL 0
+
+#elif defined __FreeBSD__
+// ----------------------------------------
+// FreeBSD
+# if __FreeBSD_version >= 400014
+# define s6_addr16 __u6_addr.__u6_addr16
+# if !defined(MSG_NOSIGNAL)
+# define MSG_NOSIGNAL 0
+# endif
+# include <netinet/in.h>
+typedef in_addr_t ipaddr_t;
+typedef in_port_t port_t;
+#ifdef SOCKETS_NAMESPACE
+namespace SOCKETS_NAMESPACE {
+#endif
+// no defs
+
+#ifdef SOCKETS_NAMESPACE
+}
+#endif
+
+# define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP
+# define IPV6_DROP_MEMBERSHIP IPV6_LEAVE_GROUP
+# else
+# error FreeBSD versions prior to 400014 does not support ipv6
+# endif
+
+#elif defined MACOSX
+// ----------------------------------------
+// Mac OS X
+#include <string.h>
+#include <mach/port.h>
+typedef unsigned long ipaddr_t;
+#ifdef SOCKETS_NAMESPACE
+namespace SOCKETS_NAMESPACE {
+#endif
+// no defs
+
+#ifdef SOCKETS_NAMESPACE
+}
+#endif
+
+#define s6_addr16 __u6_addr.__u6_addr16
+#define MSG_NOSIGNAL 0 // oops - thanks Derek
+#define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP
+#define IPV6_DROP_MEMBERSHIP IPV6_LEAVE_GROUP
+
+#elif defined _WIN32
+// ----------------------------------------
+// Win32
+#ifdef _MSC_VER
+#pragma comment(lib, "wsock32.lib")
+#endif
+#define strcasecmp _stricmp
+
+typedef unsigned long ipaddr_t;
+typedef unsigned short port_t;
+typedef int socklen_t;
+#ifdef SOCKETS_NAMESPACE
+namespace SOCKETS_NAMESPACE {
+#endif
+// no defs
+
+#ifdef SOCKETS_NAMESPACE
+}
+#endif
+
+// 1.8.6: define FD_SETSIZE to something bigger than 64 if there are a lot of
+// simultaneous connections (must be done before including winsock.h)
+//#define FD_SETSIZE 1024
+
+// windows 2000 with ipv6 preview installed:
+// http://msdn.microsoft.com/downloads/sdks/platform/tpipv6.asp
+// see the FAQ on how to install
+#define WIN32_LEAN_AND_MEAN
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#if _MSC_VER < 1200
+#ifndef __CYGWIN__
+#ifdef ENABLE_IPV6
+#include <tpipv6.h> // For IPv6 Tech Preview.
+#endif
+#endif
+#endif // _MSC_VER < 1200
+
+
+#define MSG_NOSIGNAL 0
+//#define SHUT_RDWR 2
+#define SHUT_WR 1
+
+#define Errno WSAGetLastError()
+const char *StrError(int x);
+
+#ifdef SOCKETS_NAMESPACE
+namespace SOCKETS_NAMESPACE {
+#endif
+
+
+// class WSAInitializer is a part of the Socket class (on win32)
+// as a static instance - so whenever an application uses a Socket,
+// winsock is initialized
+class WSAInitializer // Winsock Initializer
+{
+public:
+ WSAInitializer() {
+ if (WSAStartup(0x101,&m_wsadata))
+ {
+ exit(-1);
+ }
+ }
+ ~WSAInitializer() {
+ WSACleanup();
+ }
+private:
+ WSADATA m_wsadata;
+};
+
+#ifdef SOCKETS_NAMESPACE
+}
+#endif
+
+#else
+// ----------------------------------------
+// LINUX
+typedef unsigned long ipaddr_t;
+typedef unsigned short port_t;
+#ifdef SOCKETS_NAMESPACE
+namespace SOCKETS_NAMESPACE {
+#endif
+// no defs
+
+#ifdef SOCKETS_NAMESPACE
+}
+#endif
+
+
+#endif
+
+#ifdef SOCKETS_NAMESPACE
+namespace SOCKETS_NAMESPACE {
+#endif
+ /** List type containing file descriptors. */
+ typedef std::list<SOCKET> socket_v;
+
+
+#ifdef SOCKETS_NAMESPACE
+}
+#endif
+
+
+// getaddrinfo / getnameinfo replacements
+#ifdef NO_GETADDRINFO
+#ifndef AI_NUMERICHOST
+#define AI_NUMERICHOST 1
+#endif
+#ifndef NI_NUMERICHOST
+#define NI_NUMERICHOST 1
+#endif
+#endif
+
+
+#endif // _SOCKETS_socket_include_H
+
diff --git a/Sockets/sockets-config.h b/Sockets/sockets-config.h
new file mode 100644
index 0000000..dd04647
--- /dev/null
+++ b/Sockets/sockets-config.h
@@ -0,0 +1,97 @@
+/**
+ ** \file sockets-config.h
+ ** \date 2007-04-14
+ ** \author grymse@alhem.net
+**/
+/*
+Copyright (C) 2007 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.
+*/
+#ifndef _SOCKETS_CONFIG_H
+#define _SOCKETS_CONFIG_H
+
+#ifndef _RUN_DP
+/* First undefine symbols if already defined. */
+#undef HAVE_OPENSSL
+#undef ENABLE_IPV6
+#undef USE_SCTP
+#undef NO_GETADDRINFO
+#undef ENABLE_POOL
+#undef ENABLE_SOCKS4
+#undef ENABLE_RESOLVER
+#undef ENABLE_RECONNECT
+#undef ENABLE_DETACH
+#undef ENABLE_TRIGGERS
+#undef ENABLE_EXCEPTIONS
+#endif // _RUN_DP
+
+
+/* OpenSSL support. */
+#define HAVE_OPENSSL
+
+
+/* Ipv6 support. */
+//#define ENABLE_IPV6
+
+
+/* SCTP support. */
+//#define USE_SCTP
+
+
+/* Define NO_GETADDRINFO if your operating system does not support
+ the "getaddrinfo" and "getnameinfo" function calls. */
+#define NO_GETADDRINFO
+
+
+/* Connection pool support. */
+//#define ENABLE_POOL
+
+
+/* Socks4 client support. */
+//#define ENABLE_SOCKS4
+
+
+/* Asynchronous resolver. */
+#define ENABLE_RESOLVER
+
+
+/* Enable TCP reconnect on lost connection.
+ Socket::OnReconnect
+ Socket::OnDisconnect
+*/
+#define ENABLE_RECONNECT
+
+
+/* Enable socket thread detach functionality. */
+#define ENABLE_DETACH
+
+
+/* Enable socket to socket triggers. Not yet in use. */
+//#define ENABLE_TRIGGERS
+
+
+/* Enabled exceptions. */
+#define ENABLE_EXCEPTIONS
+
+
+/* Resolver uses the detach function so either enable both or disable both. */
+#ifndef ENABLE_DETACH
+#undef ENABLE_RESOLVER
+#endif
+
+
+#endif // _SOCKETS_CONFIG_H
+
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 <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/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 <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/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 <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/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 <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/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 <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/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 <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/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 <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/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 <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/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 <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/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 <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/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 <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/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 <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/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 <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/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 <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/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 <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/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 <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/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 <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);
+}
+
+
diff --git a/doc/html/PracticalSocket_8cpp.html b/doc/html/PracticalSocket_8cpp.html
index a243242..10442c5 100644
--- a/doc/html/PracticalSocket_8cpp.html
+++ b/doc/html/PracticalSocket_8cpp.html
@@ -89,7 +89,7 @@
</div>
</div><p>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/PracticalSocket_8h-source.html b/doc/html/PracticalSocket_8h-source.html
index d87328b..fb4f728 100644
--- a/doc/html/PracticalSocket_8h-source.html
+++ b/doc/html/PracticalSocket_8h-source.html
@@ -190,7 +190,7 @@
<a name="l00369"></a>00369 };
<a name="l00370"></a>00370
<a name="l00371"></a>00371 <span class="preprocessor">#endif</span>
-</pre></div><hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+</pre></div><hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:24 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/PracticalSocket_8h.html b/doc/html/PracticalSocket_8h.html
index dacd271..2c481ad 100644
--- a/doc/html/PracticalSocket_8h.html
+++ b/doc/html/PracticalSocket_8h.html
@@ -37,7 +37,7 @@
<tr><td class="memItemLeft" nowrap align="right" valign="top">class &nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="classUDPSocket.html">UDPSocket</a></td></tr>
</table>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/annotated.html b/doc/html/annotated.html
index 1c904b5..8197fa2 100644
--- a/doc/html/annotated.html
+++ b/doc/html/annotated.html
@@ -56,13 +56,14 @@
<tr><td class="indexkey"><a class="el" href="classSigUsr2Handler.html">SigUsr2Handler</a></td><td class="indexvalue"></td></tr>
<tr><td class="indexkey"><a class="el" href="classSocket.html">Socket</a></td><td class="indexvalue"></td></tr>
<tr><td class="indexkey"><a class="el" href="classSocketException.html">SocketException</a></td><td class="indexvalue"></td></tr>
+ <tr><td class="indexkey"><a class="el" href="classSyncSocket.html">SyncSocket</a></td><td class="indexvalue"></td></tr>
<tr><td class="indexkey"><a class="el" href="classTCPServerSocket.html">TCPServerSocket</a></td><td class="indexvalue"></td></tr>
<tr><td class="indexkey"><a class="el" href="classTCPSocket.html">TCPSocket</a></td><td class="indexvalue"></td></tr>
<tr><td class="indexkey"><a class="el" href="classTunDevice.html">TunDevice</a></td><td class="indexvalue"></td></tr>
<tr><td class="indexkey"><a class="el" href="classUDPPacketSource.html">UDPPacketSource</a></td><td class="indexvalue"></td></tr>
<tr><td class="indexkey"><a class="el" href="classUDPSocket.html">UDPSocket</a></td><td class="indexvalue"></td></tr>
</table>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/anytun_8cpp.html b/doc/html/anytun_8cpp.html
index 04c00dd..b20defe 100644
--- a/doc/html/anytun_8cpp.html
+++ b/doc/html/anytun_8cpp.html
@@ -44,6 +44,8 @@
<tr><td colspan="2"><br><h2>Functions</h2></td></tr>
<tr><td class="memItemLeft" nowrap align="right" valign="top">void *&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="anytun_8cpp.html#0f2bdeb94d90f5229b9e904e592b24fd">sender</a> (void *p)</td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">void *&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="anytun_8cpp.html#4fd43e7c243b1cc78c583a915dfd4d55">sync_receiver</a> (void *p)</td></tr>
+
<tr><td class="memItemLeft" nowrap align="right" valign="top">void *&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="anytun_8cpp.html#1a93139691e3d8cf8a996c973c5ca0ac">receiver</a> (void *p)</td></tr>
<tr><td class="memItemLeft" nowrap align="right" valign="top">int&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="anytun_8cpp.html#0ddf1224851353fc92bfbff6f499fa97">main</a> (int argc, char *argv[])</td></tr>
@@ -150,7 +152,27 @@
</div>
</div><p>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<a class="anchor" name="4fd43e7c243b1cc78c583a915dfd4d55"></a><!-- doxytag: member="anytun.cpp::sync_receiver" ref="4fd43e7c243b1cc78c583a915dfd4d55" args="(void *p)" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">void* sync_receiver </td>
+ <td>(</td>
+ <td class="paramtype">void *&nbsp;</td>
+ <td class="paramname"> <em>p</em> </td>
+ <td>&nbsp;)&nbsp;</td>
+ <td width="100%"></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+
+</div>
+</div><p>
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:24 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/authAlgo_8cpp.html b/doc/html/authAlgo_8cpp.html
index 7492248..96d9fd9 100644
--- a/doc/html/authAlgo_8cpp.html
+++ b/doc/html/authAlgo_8cpp.html
@@ -22,7 +22,7 @@
<table border="0" cellpadding="0" cellspacing="0">
<tr><td></td></tr>
</table>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:24 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/authAlgo_8h-source.html b/doc/html/authAlgo_8h-source.html
index eb84b2f..72ae3b7 100644
--- a/doc/html/authAlgo_8h-source.html
+++ b/doc/html/authAlgo_8h-source.html
@@ -77,7 +77,7 @@
<a name="l00058"></a>00058 };
<a name="l00059"></a>00059
<a name="l00060"></a>00060 <span class="preprocessor">#endif</span>
-</pre></div><hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+</pre></div><hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:24 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/authAlgo_8h.html b/doc/html/authAlgo_8h.html
index 5681197..6691c03 100644
--- a/doc/html/authAlgo_8h.html
+++ b/doc/html/authAlgo_8h.html
@@ -31,7 +31,7 @@
<tr><td class="memItemLeft" nowrap align="right" valign="top">class &nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="classHmacAuthAlgo.html">HmacAuthAlgo</a></td></tr>
</table>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:24 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/buffer_8cpp.html b/doc/html/buffer_8cpp.html
index 1d724a7..30ee9db 100644
--- a/doc/html/buffer_8cpp.html
+++ b/doc/html/buffer_8cpp.html
@@ -26,7 +26,7 @@
<table border="0" cellpadding="0" cellspacing="0">
<tr><td></td></tr>
</table>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:24 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/buffer_8h-source.html b/doc/html/buffer_8h-source.html
index d949db4..3cd42f4 100644
--- a/doc/html/buffer_8h-source.html
+++ b/doc/html/buffer_8h-source.html
@@ -93,7 +93,7 @@
<a name="l00074"></a>00074 };
<a name="l00075"></a>00075
<a name="l00076"></a>00076 <span class="preprocessor">#endif</span>
-</pre></div><hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+</pre></div><hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:24 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/buffer_8h.html b/doc/html/buffer_8h.html
index 329e5e6..7ac3de9 100644
--- a/doc/html/buffer_8h.html
+++ b/doc/html/buffer_8h.html
@@ -26,7 +26,7 @@
<tr><td class="memItemLeft" nowrap align="right" valign="top">class &nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="classBuffer.html">Buffer</a></td></tr>
</table>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:24 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/classAesIcmCypher-members.html b/doc/html/classAesIcmCypher-members.html
index ff66cca..ce31628 100644
--- a/doc/html/classAesIcmCypher-members.html
+++ b/doc/html/classAesIcmCypher-members.html
@@ -33,7 +33,7 @@
<tr class="memlist"><td><a class="el" href="classAesIcmCypher.html#6741487a9d6dfe3ae76bb168ed711259">setSalt</a>(Buffer salt)</td><td><a class="el" href="classAesIcmCypher.html">AesIcmCypher</a></td><td></td></tr>
<tr class="memlist"><td><a class="el" href="classAesIcmCypher.html#fdf9ab22374ffdad856f172eefacbd17">~AesIcmCypher</a>()</td><td><a class="el" href="classAesIcmCypher.html">AesIcmCypher</a></td><td></td></tr>
<tr class="memlist"><td><a class="el" href="classCypher.html#70c94525f7bacb956cdd940fba7fb4c8">~Cypher</a>()</td><td><a class="el" href="classCypher.html">Cypher</a></td><td><code> [inline, virtual]</code></td></tr>
-</table><hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+</table><hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/classAesIcmCypher.html b/doc/html/classAesIcmCypher.html
index 23559a7..8c53211 100644
--- a/doc/html/classAesIcmCypher.html
+++ b/doc/html/classAesIcmCypher.html
@@ -252,7 +252,7 @@ Implements <a class="el" href="classCypher.html#7ddf1bcd476978daa97148ec406d6483
</div><p>
<hr>The documentation for this class was generated from the following files:<ul>
<li><a class="el" href="cypher_8h-source.html">cypher.h</a><li><a class="el" href="cypher_8cpp.html">cypher.cpp</a></ul>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/classAuthAlgo-members.html b/doc/html/classAuthAlgo-members.html
index 507b2bf..47c622b 100644
--- a/doc/html/classAuthAlgo-members.html
+++ b/doc/html/classAuthAlgo-members.html
@@ -22,7 +22,7 @@
<tr class="memlist"><td><a class="el" href="classAuthAlgo.html#22a200c372d9aeb73a4cbdd95ba30a0e">AuthAlgo</a>()</td><td><a class="el" href="classAuthAlgo.html">AuthAlgo</a></td><td><code> [inline]</code></td></tr>
<tr class="memlist"><td><a class="el" href="classAuthAlgo.html#f53b44f90c33eb049da260947a75c916">calc</a>(const Buffer &amp;buf)=0</td><td><a class="el" href="classAuthAlgo.html">AuthAlgo</a></td><td><code> [pure virtual]</code></td></tr>
<tr class="memlist"><td><a class="el" href="classAuthAlgo.html#e3428186b4e005e879e26c2b8e04fa4a">~AuthAlgo</a>()</td><td><a class="el" href="classAuthAlgo.html">AuthAlgo</a></td><td><code> [inline, virtual]</code></td></tr>
-</table><hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+</table><hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/classAuthAlgo.html b/doc/html/classAuthAlgo.html
index 114762a..59bf63a 100644
--- a/doc/html/classAuthAlgo.html
+++ b/doc/html/classAuthAlgo.html
@@ -100,7 +100,7 @@ Implemented in <a class="el" href="classNullAuthAlgo.html#60eead12d6b32a576ad40d
</div><p>
<hr>The documentation for this class was generated from the following file:<ul>
<li><a class="el" href="authAlgo_8h-source.html">authAlgo.h</a></ul>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/classBuffer-members.html b/doc/html/classBuffer-members.html
index d8d9c12..5da6ef5 100644
--- a/doc/html/classBuffer-members.html
+++ b/doc/html/classBuffer-members.html
@@ -42,7 +42,7 @@
<tr class="memlist"><td><a class="el" href="classBuffer.html#51b494563d277beb4740f86c519f30fb">TunDevice</a> class</td><td><a class="el" href="classBuffer.html">Buffer</a></td><td><code> [friend]</code></td></tr>
<tr class="memlist"><td><a class="el" href="classBuffer.html#940a382a5e3a8622e6689e13dc453481">UDPPacketSource</a> class</td><td><a class="el" href="classBuffer.html">Buffer</a></td><td><code> [friend]</code></td></tr>
<tr class="memlist"><td><a class="el" href="classBuffer.html#59b8743e4a5f731bdd0c4185c9ef263b">~Buffer</a>()</td><td><a class="el" href="classBuffer.html">Buffer</a></td><td><code> [virtual]</code></td></tr>
-</table><hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+</table><hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/classBuffer.html b/doc/html/classBuffer.html
index b31bff4..63ee8c2 100644
--- a/doc/html/classBuffer.html
+++ b/doc/html/classBuffer.html
@@ -527,7 +527,7 @@
</div><p>
<hr>The documentation for this class was generated from the following files:<ul>
<li><a class="el" href="buffer_8h-source.html">buffer.h</a><li><a class="el" href="buffer_8cpp.html">buffer.cpp</a></ul>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/classCommunicatingSocket-members.html b/doc/html/classCommunicatingSocket-members.html
index a629f55..7c80934 100644
--- a/doc/html/classCommunicatingSocket-members.html
+++ b/doc/html/classCommunicatingSocket-members.html
@@ -36,7 +36,7 @@
<tr class="memlist"><td><a class="el" href="classSocket.html#53e00027bab2125a2b407914c6148589">Socket</a>(int type, int protocol)</td><td><a class="el" href="classSocket.html">Socket</a></td><td><code> [protected]</code></td></tr>
<tr class="memlist"><td><a class="el" href="classSocket.html#6a2609eef6559336a595a336f138d395">Socket</a>(int sockDesc)</td><td><a class="el" href="classSocket.html">Socket</a></td><td><code> [protected]</code></td></tr>
<tr class="memlist"><td><a class="el" href="classSocket.html#eac4eb6379a543d38ed88977d3b6630a">~Socket</a>()</td><td><a class="el" href="classSocket.html">Socket</a></td><td></td></tr>
-</table><hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+</table><hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/classCommunicatingSocket.html b/doc/html/classCommunicatingSocket.html
index 66e5a3d..4015647 100644
--- a/doc/html/classCommunicatingSocket.html
+++ b/doc/html/classCommunicatingSocket.html
@@ -274,7 +274,7 @@ Get the foreign port. Call <a class="el" href="classCommunicatingSocket.html#919
</div><p>
<hr>The documentation for this class was generated from the following files:<ul>
<li><a class="el" href="PracticalSocket_8h-source.html">PracticalSocket.h</a><li><a class="el" href="PracticalSocket_8cpp.html">PracticalSocket.cpp</a></ul>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/classCondition-members.html b/doc/html/classCondition-members.html
index 2509148..158a05d 100644
--- a/doc/html/classCondition-members.html
+++ b/doc/html/classCondition-members.html
@@ -26,7 +26,7 @@
<tr class="memlist"><td><a class="el" href="classCondition.html#974c8fd419e6014028dc4147cc49ce56">signal</a>()</td><td><a class="el" href="classCondition.html">Condition</a></td><td><code> [inline]</code></td></tr>
<tr class="memlist"><td><a class="el" href="classCondition.html#0bb9ca22c3c755d0ed8c7483a857567a">wait</a>()</td><td><a class="el" href="classCondition.html">Condition</a></td><td><code> [inline]</code></td></tr>
<tr class="memlist"><td><a class="el" href="classCondition.html#b42f6d2dfb2d0de4bed4ed5032d4a8fc">~Condition</a>()</td><td><a class="el" href="classCondition.html">Condition</a></td><td><code> [inline]</code></td></tr>
-</table><hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+</table><hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/classCondition.html b/doc/html/classCondition.html
index 6741a66..9f8b676 100644
--- a/doc/html/classCondition.html
+++ b/doc/html/classCondition.html
@@ -169,7 +169,7 @@
</div><p>
<hr>The documentation for this class was generated from the following file:<ul>
<li><a class="el" href="threadUtils_8hpp-source.html">threadUtils.hpp</a></ul>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/classCypher-members.html b/doc/html/classCypher-members.html
index 3ff10bd..18e53fb 100644
--- a/doc/html/classCypher-members.html
+++ b/doc/html/classCypher-members.html
@@ -26,7 +26,7 @@
<tr class="memlist"><td><a class="el" href="classCypher.html#7320b82d14391ab7d25271aa5114e190">setKey</a>(Buffer key)</td><td><a class="el" href="classCypher.html">Cypher</a></td><td><code> [inline]</code></td></tr>
<tr class="memlist"><td><a class="el" href="classCypher.html#2546ef49e5ce8abe8062186d5f6b2ef8">setSalt</a>(Buffer salt)</td><td><a class="el" href="classCypher.html">Cypher</a></td><td><code> [inline]</code></td></tr>
<tr class="memlist"><td><a class="el" href="classCypher.html#70c94525f7bacb956cdd940fba7fb4c8">~Cypher</a>()</td><td><a class="el" href="classCypher.html">Cypher</a></td><td><code> [inline, virtual]</code></td></tr>
-</table><hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+</table><hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/classCypher.html b/doc/html/classCypher.html
index f952f18..d20b56f 100644
--- a/doc/html/classCypher.html
+++ b/doc/html/classCypher.html
@@ -232,7 +232,7 @@ Implemented in <a class="el" href="classNullCypher.html#ca537adca8ea9af8b6f248df
</div><p>
<hr>The documentation for this class was generated from the following files:<ul>
<li><a class="el" href="cypher_8h-source.html">cypher.h</a><li><a class="el" href="cypher_8cpp.html">cypher.cpp</a></ul>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/classHmacAuthAlgo-members.html b/doc/html/classHmacAuthAlgo-members.html
index 2b4116f..49a09aa 100644
--- a/doc/html/classHmacAuthAlgo-members.html
+++ b/doc/html/classHmacAuthAlgo-members.html
@@ -22,7 +22,7 @@
<tr class="memlist"><td><a class="el" href="classAuthAlgo.html#22a200c372d9aeb73a4cbdd95ba30a0e">AuthAlgo</a>()</td><td><a class="el" href="classAuthAlgo.html">AuthAlgo</a></td><td><code> [inline]</code></td></tr>
<tr class="memlist"><td><a class="el" href="classHmacAuthAlgo.html#af50c9aa6b61ff6f4631e3f78f77dc97">calc</a>(const Buffer &amp;buf)</td><td><a class="el" href="classHmacAuthAlgo.html">HmacAuthAlgo</a></td><td><code> [virtual]</code></td></tr>
<tr class="memlist"><td><a class="el" href="classAuthAlgo.html#e3428186b4e005e879e26c2b8e04fa4a">~AuthAlgo</a>()</td><td><a class="el" href="classAuthAlgo.html">AuthAlgo</a></td><td><code> [inline, virtual]</code></td></tr>
-</table><hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+</table><hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/classHmacAuthAlgo.html b/doc/html/classHmacAuthAlgo.html
index ca665e7..6011d99 100644
--- a/doc/html/classHmacAuthAlgo.html
+++ b/doc/html/classHmacAuthAlgo.html
@@ -56,7 +56,7 @@ Implements <a class="el" href="classAuthAlgo.html#f53b44f90c33eb049da260947a75c9
</div><p>
<hr>The documentation for this class was generated from the following files:<ul>
<li><a class="el" href="authAlgo_8h-source.html">authAlgo.h</a><li><a class="el" href="authAlgo_8cpp.html">authAlgo.cpp</a></ul>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/classKeyDerivation-members.html b/doc/html/classKeyDerivation-members.html
index ca924f2..cc9f3cd 100644
--- a/doc/html/classKeyDerivation-members.html
+++ b/doc/html/classKeyDerivation-members.html
@@ -29,7 +29,7 @@
<tr class="memlist"><td><a class="el" href="classKeyDerivation.html#52e057f1085920a61ea44c5c9936865c">salt_</a></td><td><a class="el" href="classKeyDerivation.html">KeyDerivation</a></td><td><code> [protected]</code></td></tr>
<tr class="memlist"><td><a class="el" href="classKeyDerivation.html#b055afc0de04a6e32631e42f09b32e63">setLogKDRate</a>(const u_int8_t ld_rate)</td><td><a class="el" href="classKeyDerivation.html">KeyDerivation</a></td><td></td></tr>
<tr class="memlist"><td><a class="el" href="classKeyDerivation.html#ccce2c32370be2388ca0a977fef1f6cc">~KeyDerivation</a>()</td><td><a class="el" href="classKeyDerivation.html">KeyDerivation</a></td><td><code> [inline, virtual]</code></td></tr>
-</table><hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+</table><hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/classKeyDerivation.html b/doc/html/classKeyDerivation.html
index c997f13..1f3cbe1 100644
--- a/doc/html/classKeyDerivation.html
+++ b/doc/html/classKeyDerivation.html
@@ -258,7 +258,7 @@
</div><p>
<hr>The documentation for this class was generated from the following files:<ul>
<li><a class="el" href="keyDerivation_8h-source.html">keyDerivation.h</a><li><a class="el" href="keyDerivation_8cpp.html">keyDerivation.cpp</a></ul>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/classLock-members.html b/doc/html/classLock-members.html
index 3d8d73f..cdfc830 100644
--- a/doc/html/classLock-members.html
+++ b/doc/html/classLock-members.html
@@ -24,7 +24,7 @@
<tr class="memlist"><td><a class="el" href="classLock.html#41f8817641e260bddb93a7a710736037">mutex</a></td><td><a class="el" href="classLock.html">Lock</a></td><td><code> [private]</code></td></tr>
<tr class="memlist"><td><a class="el" href="classLock.html#6beb534a89b213d70e4b3bb9b3cde217">operator=</a>(const Lock &amp;src)</td><td><a class="el" href="classLock.html">Lock</a></td><td><code> [private]</code></td></tr>
<tr class="memlist"><td><a class="el" href="classLock.html#7ab6d9485c8665bb3643710432882971">~Lock</a>()</td><td><a class="el" href="classLock.html">Lock</a></td><td><code> [inline]</code></td></tr>
-</table><hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+</table><hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/classLock.html b/doc/html/classLock.html
index bd3df71..97a9388 100644
--- a/doc/html/classLock.html
+++ b/doc/html/classLock.html
@@ -135,7 +135,7 @@
</div><p>
<hr>The documentation for this class was generated from the following file:<ul>
<li><a class="el" href="threadUtils_8hpp-source.html">threadUtils.hpp</a></ul>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/classLog-members.html b/doc/html/classLog-members.html
index 0e2cacf..57ce2b9 100644
--- a/doc/html/classLog-members.html
+++ b/doc/html/classLog-members.html
@@ -64,7 +64,7 @@
<tr class="memlist"><td><a class="el" href="classLog.html#828e15ec0e9108b9fc43d74da77a902c">setFacility</a>(int newFacility)</td><td><a class="el" href="classLog.html">Log</a></td><td></td></tr>
<tr class="memlist"><td><a class="el" href="classLog.html#f8cf0541a8284aabd5fe924a9cd2eab8">setLogName</a>(std::string newLogName)</td><td><a class="el" href="classLog.html">Log</a></td><td></td></tr>
<tr class="memlist"><td><a class="el" href="classLog.html#0fbfda88fbee5027c89f6eb121059360">~Log</a>()</td><td><a class="el" href="classLog.html">Log</a></td><td><code> [private]</code></td></tr>
-</table><hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+</table><hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/classLog.html b/doc/html/classLog.html
index 5d2ff2f..f158ffe 100644
--- a/doc/html/classLog.html
+++ b/doc/html/classLog.html
@@ -853,7 +853,7 @@
</div><p>
<hr>The documentation for this class was generated from the following files:<ul>
<li><a class="el" href="log_8h-source.html">log.h</a><li><a class="el" href="log_8cpp.html">log.cpp</a></ul>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/classLogStringBuilder-members.html b/doc/html/classLogStringBuilder-members.html
index 6115ffa..b9be18d 100644
--- a/doc/html/classLogStringBuilder-members.html
+++ b/doc/html/classLogStringBuilder-members.html
@@ -26,7 +26,7 @@
<tr class="memlist"><td><a class="el" href="classLogStringBuilder.html#89d48a7590de117fec0b40c0babbaee5">prio</a></td><td><a class="el" href="classLogStringBuilder.html">LogStringBuilder</a></td><td><code> [private]</code></td></tr>
<tr class="memlist"><td><a class="el" href="classLogStringBuilder.html#405447561d3d7337cc093dad6c6d81b5">stream</a></td><td><a class="el" href="classLogStringBuilder.html">LogStringBuilder</a></td><td><code> [private]</code></td></tr>
<tr class="memlist"><td><a class="el" href="classLogStringBuilder.html#c63707864e0005008cc4a67d8dec9933">~LogStringBuilder</a>()</td><td><a class="el" href="classLogStringBuilder.html">LogStringBuilder</a></td><td></td></tr>
-</table><hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+</table><hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/classLogStringBuilder.html b/doc/html/classLogStringBuilder.html
index 403e353..3282308 100644
--- a/doc/html/classLogStringBuilder.html
+++ b/doc/html/classLogStringBuilder.html
@@ -180,7 +180,7 @@ template&lt;class T&gt; </div>
</div><p>
<hr>The documentation for this class was generated from the following files:<ul>
<li><a class="el" href="log_8h-source.html">log.h</a><li><a class="el" href="log_8cpp.html">log.cpp</a></ul>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/classLog_1_1instanceCleaner-members.html b/doc/html/classLog_1_1instanceCleaner-members.html
index c5cf53a..1fdccc7 100644
--- a/doc/html/classLog_1_1instanceCleaner-members.html
+++ b/doc/html/classLog_1_1instanceCleaner-members.html
@@ -20,7 +20,7 @@
</ul></div>
<h1>Log::instanceCleaner Member List</h1>This is the complete list of members for <a class="el" href="classLog_1_1instanceCleaner.html">Log::instanceCleaner</a>, including all inherited members.<p><table>
<tr class="memlist"><td><a class="el" href="classLog_1_1instanceCleaner.html#5e2dd96e4f58345bd2067cd40fbec865">~instanceCleaner</a>()</td><td><a class="el" href="classLog_1_1instanceCleaner.html">Log::instanceCleaner</a></td><td><code> [inline]</code></td></tr>
-</table><hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+</table><hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/classLog_1_1instanceCleaner.html b/doc/html/classLog_1_1instanceCleaner.html
index d7ea77f..39bc6be 100644
--- a/doc/html/classLog_1_1instanceCleaner.html
+++ b/doc/html/classLog_1_1instanceCleaner.html
@@ -48,7 +48,7 @@
</div><p>
<hr>The documentation for this class was generated from the following file:<ul>
<li><a class="el" href="log_8h-source.html">log.h</a></ul>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/classMutex-members.html b/doc/html/classMutex-members.html
index 22b778d..ac4a5a7 100644
--- a/doc/html/classMutex-members.html
+++ b/doc/html/classMutex-members.html
@@ -28,7 +28,7 @@
<tr class="memlist"><td><a class="el" href="classMutex.html#030a11400d00ef97813c6b232a5e3f43">operator=</a>(const Mutex &amp;src)</td><td><a class="el" href="classMutex.html">Mutex</a></td><td><code> [private]</code></td></tr>
<tr class="memlist"><td><a class="el" href="classMutex.html#546a5b797ba29959357586aa2b3740a8">unlock</a>()</td><td><a class="el" href="classMutex.html">Mutex</a></td><td><code> [inline, private]</code></td></tr>
<tr class="memlist"><td><a class="el" href="classMutex.html#c9e9182407f5f74892318607888e9be4">~Mutex</a>()</td><td><a class="el" href="classMutex.html">Mutex</a></td><td><code> [inline]</code></td></tr>
-</table><hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+</table><hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/classMutex.html b/doc/html/classMutex.html
index d6ecdf0..590872f 100644
--- a/doc/html/classMutex.html
+++ b/doc/html/classMutex.html
@@ -212,7 +212,7 @@
</div><p>
<hr>The documentation for this class was generated from the following file:<ul>
<li><a class="el" href="threadUtils_8hpp-source.html">threadUtils.hpp</a></ul>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/classNullAuthAlgo-members.html b/doc/html/classNullAuthAlgo-members.html
index 9fb3fcc..8d99c3a 100644
--- a/doc/html/classNullAuthAlgo-members.html
+++ b/doc/html/classNullAuthAlgo-members.html
@@ -22,7 +22,7 @@
<tr class="memlist"><td><a class="el" href="classAuthAlgo.html#22a200c372d9aeb73a4cbdd95ba30a0e">AuthAlgo</a>()</td><td><a class="el" href="classAuthAlgo.html">AuthAlgo</a></td><td><code> [inline]</code></td></tr>
<tr class="memlist"><td><a class="el" href="classNullAuthAlgo.html#60eead12d6b32a576ad40d999a6151cf">calc</a>(const Buffer &amp;buf)</td><td><a class="el" href="classNullAuthAlgo.html">NullAuthAlgo</a></td><td><code> [virtual]</code></td></tr>
<tr class="memlist"><td><a class="el" href="classAuthAlgo.html#e3428186b4e005e879e26c2b8e04fa4a">~AuthAlgo</a>()</td><td><a class="el" href="classAuthAlgo.html">AuthAlgo</a></td><td><code> [inline, virtual]</code></td></tr>
-</table><hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+</table><hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/classNullAuthAlgo.html b/doc/html/classNullAuthAlgo.html
index abd1385..7534505 100644
--- a/doc/html/classNullAuthAlgo.html
+++ b/doc/html/classNullAuthAlgo.html
@@ -56,7 +56,7 @@ Implements <a class="el" href="classAuthAlgo.html#f53b44f90c33eb049da260947a75c9
</div><p>
<hr>The documentation for this class was generated from the following files:<ul>
<li><a class="el" href="authAlgo_8h-source.html">authAlgo.h</a><li><a class="el" href="authAlgo_8cpp.html">authAlgo.cpp</a></ul>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/classNullCypher-members.html b/doc/html/classNullCypher-members.html
index d96e935..33a6156 100644
--- a/doc/html/classNullCypher-members.html
+++ b/doc/html/classNullCypher-members.html
@@ -26,7 +26,7 @@
<tr class="memlist"><td><a class="el" href="classCypher.html#7320b82d14391ab7d25271aa5114e190">setKey</a>(Buffer key)</td><td><a class="el" href="classCypher.html">Cypher</a></td><td><code> [inline]</code></td></tr>
<tr class="memlist"><td><a class="el" href="classCypher.html#2546ef49e5ce8abe8062186d5f6b2ef8">setSalt</a>(Buffer salt)</td><td><a class="el" href="classCypher.html">Cypher</a></td><td><code> [inline]</code></td></tr>
<tr class="memlist"><td><a class="el" href="classCypher.html#70c94525f7bacb956cdd940fba7fb4c8">~Cypher</a>()</td><td><a class="el" href="classCypher.html">Cypher</a></td><td><code> [inline, virtual]</code></td></tr>
-</table><hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+</table><hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/classNullCypher.html b/doc/html/classNullCypher.html
index ca4697f..c06e693 100644
--- a/doc/html/classNullCypher.html
+++ b/doc/html/classNullCypher.html
@@ -71,7 +71,7 @@ Implements <a class="el" href="classCypher.html#7ddf1bcd476978daa97148ec406d6483
</div><p>
<hr>The documentation for this class was generated from the following files:<ul>
<li><a class="el" href="cypher_8h-source.html">cypher.h</a><li><a class="el" href="cypher_8cpp.html">cypher.cpp</a></ul>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/classOptions-members.html b/doc/html/classOptions-members.html
index 8d82abc..e259c59 100644
--- a/doc/html/classOptions-members.html
+++ b/doc/html/classOptions-members.html
@@ -70,7 +70,7 @@
<tr class="memlist"><td><a class="el" href="classOptions.html#cbd3e9a4e230c2537d86127a092efd40">setRemotePort</a>(u_int16_t r)</td><td><a class="el" href="classOptions.html">Options</a></td><td></td></tr>
<tr class="memlist"><td><a class="el" href="classOptions.html#d10f65b29130c7e31a332e22f77650b0">setSenderId</a>(sender_id_t s)</td><td><a class="el" href="classOptions.html">Options</a></td><td></td></tr>
<tr class="memlist"><td><a class="el" href="classOptions.html#077dda754c64b01d6736aa4f7862ce6b">setSeqWindowSize</a>(window_size_t s)</td><td><a class="el" href="classOptions.html">Options</a></td><td></td></tr>
-</table><hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+</table><hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/classOptions.html b/doc/html/classOptions.html
index c2a66e6..23598ea 100644
--- a/doc/html/classOptions.html
+++ b/doc/html/classOptions.html
@@ -1072,7 +1072,7 @@
</div><p>
<hr>The documentation for this class was generated from the following files:<ul>
<li><a class="el" href="options_8h-source.html">options.h</a><li><a class="el" href="options_8cpp.html">options.cpp</a></ul>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/classPacket-members.html b/doc/html/classPacket-members.html
index 852778c..7a2de31 100644
--- a/doc/html/classPacket-members.html
+++ b/doc/html/classPacket-members.html
@@ -67,7 +67,7 @@
<tr class="memlist"><td><a class="el" href="classPacket.html#ce9e40180f64d44fe1d8da14ac9e5df2">withHeader</a>(bool b)</td><td><a class="el" href="classPacket.html">Packet</a></td><td></td></tr>
<tr class="memlist"><td><a class="el" href="classPacket.html#c7ecfc05376afd00af89cb328e194a1d">withPayloadType</a>(bool b)</td><td><a class="el" href="classPacket.html">Packet</a></td><td></td></tr>
<tr class="memlist"><td><a class="el" href="classBuffer.html#59b8743e4a5f731bdd0c4185c9ef263b">~Buffer</a>()</td><td><a class="el" href="classBuffer.html">Buffer</a></td><td><code> [virtual]</code></td></tr>
-</table><hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+</table><hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/classPacket.html b/doc/html/classPacket.html
index 90bd26c..8bffd60 100644
--- a/doc/html/classPacket.html
+++ b/doc/html/classPacket.html
@@ -567,7 +567,7 @@
</div><p>
<hr>The documentation for this class was generated from the following files:<ul>
<li><a class="el" href="packet_8h-source.html">packet.h</a><li><a class="el" href="packet_8cpp.html">packet.cpp</a></ul>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/classPacketSource-members.html b/doc/html/classPacketSource-members.html
index 41d68ef..68c208c 100644
--- a/doc/html/classPacketSource-members.html
+++ b/doc/html/classPacketSource-members.html
@@ -22,7 +22,7 @@
<tr class="memlist"><td><a class="el" href="classPacketSource.html#95901be715656540a7273c6c0dc1234e">recv</a>(Buffer &amp;buf, std::string &amp;addr, u_int16_t &amp;port)=0</td><td><a class="el" href="classPacketSource.html">PacketSource</a></td><td><code> [pure virtual]</code></td></tr>
<tr class="memlist"><td><a class="el" href="classPacketSource.html#ffc5eb2c89d1395443432c3cc6b7898b">send</a>(Buffer &amp;buf, std::string addr, u_int16_t port)=0</td><td><a class="el" href="classPacketSource.html">PacketSource</a></td><td><code> [pure virtual]</code></td></tr>
<tr class="memlist"><td><a class="el" href="classPacketSource.html#fdaad665e453cf5a047935b07a050ef4">~PacketSource</a>()</td><td><a class="el" href="classPacketSource.html">PacketSource</a></td><td><code> [inline, virtual]</code></td></tr>
-</table><hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+</table><hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/classPacketSource.html b/doc/html/classPacketSource.html
index 3e404d1..f55abb0 100644
--- a/doc/html/classPacketSource.html
+++ b/doc/html/classPacketSource.html
@@ -132,7 +132,7 @@ Implemented in <a class="el" href="classUDPPacketSource.html#376a3b0c861aeb7561e
</div><p>
<hr>The documentation for this class was generated from the following file:<ul>
<li><a class="el" href="packetSource_8h-source.html">packetSource.h</a></ul>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/classSemaphore-members.html b/doc/html/classSemaphore-members.html
index 8d7f16e..adaf15f 100644
--- a/doc/html/classSemaphore-members.html
+++ b/doc/html/classSemaphore-members.html
@@ -24,7 +24,7 @@
<tr class="memlist"><td><a class="el" href="classSemaphore.html#570698c680a467b9b0a708635149d54a">Semaphore</a>(unsigned int initVal=0)</td><td><a class="el" href="classSemaphore.html">Semaphore</a></td><td><code> [inline]</code></td></tr>
<tr class="memlist"><td><a class="el" href="classSemaphore.html#15fb190263808234fc2562f39f523082">up</a>()</td><td><a class="el" href="classSemaphore.html">Semaphore</a></td><td><code> [inline]</code></td></tr>
<tr class="memlist"><td><a class="el" href="classSemaphore.html#633658a6fde276bffc912028725c6ade">~Semaphore</a>()</td><td><a class="el" href="classSemaphore.html">Semaphore</a></td><td><code> [inline]</code></td></tr>
-</table><hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+</table><hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/classSemaphore.html b/doc/html/classSemaphore.html
index 22583a1..846d6f5 100644
--- a/doc/html/classSemaphore.html
+++ b/doc/html/classSemaphore.html
@@ -132,7 +132,7 @@
</div><p>
<hr>The documentation for this class was generated from the following file:<ul>
<li><a class="el" href="threadUtils_8hpp-source.html">threadUtils.hpp</a></ul>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/classSeqWindow-members.html b/doc/html/classSeqWindow-members.html
index 54c2866..1ef47da 100644
--- a/doc/html/classSeqWindow-members.html
+++ b/doc/html/classSeqWindow-members.html
@@ -33,7 +33,7 @@
<tr class="memlist"><td><a class="el" href="classSeqWindow.html#7a30b232f312d843b8d188cae01fef28">SeqWindow</a>(const SeqWindow &amp;s)</td><td><a class="el" href="classSeqWindow.html">SeqWindow</a></td><td><code> [private]</code></td></tr>
<tr class="memlist"><td><a class="el" href="classSeqWindow.html#ef85ba28f8a655dc8c8d34aeddb8eea0">window_size_</a></td><td><a class="el" href="classSeqWindow.html">SeqWindow</a></td><td><code> [private]</code></td></tr>
<tr class="memlist"><td><a class="el" href="classSeqWindow.html#d125bcc4751a746427f04dda7fd65a10">~SeqWindow</a>()</td><td><a class="el" href="classSeqWindow.html">SeqWindow</a></td><td></td></tr>
-</table><hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+</table><hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/classSeqWindow.html b/doc/html/classSeqWindow.html
index cab6f28..3473e09 100644
--- a/doc/html/classSeqWindow.html
+++ b/doc/html/classSeqWindow.html
@@ -333,7 +333,7 @@
</div><p>
<hr>The documentation for this class was generated from the following files:<ul>
<li><a class="el" href="seqWindow_8h-source.html">seqWindow.h</a><li><a class="el" href="seqWindow_8cpp.html">seqWindow.cpp</a></ul>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/classSigHupHandler-members.html b/doc/html/classSigHupHandler-members.html
index a8c329a..d3d0bd7 100644
--- a/doc/html/classSigHupHandler-members.html
+++ b/doc/html/classSigHupHandler-members.html
@@ -23,7 +23,7 @@
<tr class="memlist"><td><a class="el" href="classSigHupHandler.html#a1ee03b63ca11d8b5aae82fae1f2d6a3">SigHupHandler</a>()</td><td><a class="el" href="classSigHupHandler.html">SigHupHandler</a></td><td><code> [inline]</code></td></tr>
<tr class="memlist"><td><a class="el" href="classSignalHandler.html#8f920534650e9cd3cdfbe3c3f8409b4d">SignalHandler</a>(int s)</td><td><a class="el" href="classSignalHandler.html">SignalHandler</a></td><td><code> [inline, protected]</code></td></tr>
<tr class="memlist"><td><a class="el" href="classSignalHandler.html#a1109d38f8b43bde75420aaeecc1f2b7">~SignalHandler</a>()</td><td><a class="el" href="classSignalHandler.html">SignalHandler</a></td><td><code> [inline, virtual]</code></td></tr>
-</table><hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+</table><hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/classSigHupHandler.html b/doc/html/classSigHupHandler.html
index 3c5df42..eafbcd0 100644
--- a/doc/html/classSigHupHandler.html
+++ b/doc/html/classSigHupHandler.html
@@ -77,7 +77,7 @@ Reimplemented from <a class="el" href="classSignalHandler.html#e3dbda0de9b4aa454
</div><p>
<hr>The documentation for this class was generated from the following files:<ul>
<li><a class="el" href="signalController_8h-source.html">signalController.h</a><li><a class="el" href="signalController_8cpp.html">signalController.cpp</a></ul>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/classSigIntHandler-members.html b/doc/html/classSigIntHandler-members.html
index 71a1450..c6e66c1 100644
--- a/doc/html/classSigIntHandler-members.html
+++ b/doc/html/classSigIntHandler-members.html
@@ -23,7 +23,7 @@
<tr class="memlist"><td><a class="el" href="classSigIntHandler.html#ac25b5ac048a76d4c0c26d5ad4c4273d">SigIntHandler</a>()</td><td><a class="el" href="classSigIntHandler.html">SigIntHandler</a></td><td><code> [inline]</code></td></tr>
<tr class="memlist"><td><a class="el" href="classSignalHandler.html#8f920534650e9cd3cdfbe3c3f8409b4d">SignalHandler</a>(int s)</td><td><a class="el" href="classSignalHandler.html">SignalHandler</a></td><td><code> [inline, protected]</code></td></tr>
<tr class="memlist"><td><a class="el" href="classSignalHandler.html#a1109d38f8b43bde75420aaeecc1f2b7">~SignalHandler</a>()</td><td><a class="el" href="classSignalHandler.html">SignalHandler</a></td><td><code> [inline, virtual]</code></td></tr>
-</table><hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+</table><hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/classSigIntHandler.html b/doc/html/classSigIntHandler.html
index f5bbc71..5e17b28 100644
--- a/doc/html/classSigIntHandler.html
+++ b/doc/html/classSigIntHandler.html
@@ -77,7 +77,7 @@ Reimplemented from <a class="el" href="classSignalHandler.html#e3dbda0de9b4aa454
</div><p>
<hr>The documentation for this class was generated from the following files:<ul>
<li><a class="el" href="signalController_8h-source.html">signalController.h</a><li><a class="el" href="signalController_8cpp.html">signalController.cpp</a></ul>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/classSigQuitHandler-members.html b/doc/html/classSigQuitHandler-members.html
index 789ee11..b11bf68 100644
--- a/doc/html/classSigQuitHandler-members.html
+++ b/doc/html/classSigQuitHandler-members.html
@@ -23,7 +23,7 @@
<tr class="memlist"><td><a class="el" href="classSignalHandler.html#8f920534650e9cd3cdfbe3c3f8409b4d">SignalHandler</a>(int s)</td><td><a class="el" href="classSignalHandler.html">SignalHandler</a></td><td><code> [inline, protected]</code></td></tr>
<tr class="memlist"><td><a class="el" href="classSigQuitHandler.html#45885e5ddfa14f9bfc13c72de425e1c6">SigQuitHandler</a>()</td><td><a class="el" href="classSigQuitHandler.html">SigQuitHandler</a></td><td><code> [inline]</code></td></tr>
<tr class="memlist"><td><a class="el" href="classSignalHandler.html#a1109d38f8b43bde75420aaeecc1f2b7">~SignalHandler</a>()</td><td><a class="el" href="classSignalHandler.html">SignalHandler</a></td><td><code> [inline, virtual]</code></td></tr>
-</table><hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+</table><hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/classSigQuitHandler.html b/doc/html/classSigQuitHandler.html
index aaab37b..f878f0a 100644
--- a/doc/html/classSigQuitHandler.html
+++ b/doc/html/classSigQuitHandler.html
@@ -77,7 +77,7 @@ Reimplemented from <a class="el" href="classSignalHandler.html#e3dbda0de9b4aa454
</div><p>
<hr>The documentation for this class was generated from the following files:<ul>
<li><a class="el" href="signalController_8h-source.html">signalController.h</a><li><a class="el" href="signalController_8cpp.html">signalController.cpp</a></ul>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/classSigTermHandler-members.html b/doc/html/classSigTermHandler-members.html
index 715525c..3280b9e 100644
--- a/doc/html/classSigTermHandler-members.html
+++ b/doc/html/classSigTermHandler-members.html
@@ -23,7 +23,7 @@
<tr class="memlist"><td><a class="el" href="classSignalHandler.html#8f920534650e9cd3cdfbe3c3f8409b4d">SignalHandler</a>(int s)</td><td><a class="el" href="classSignalHandler.html">SignalHandler</a></td><td><code> [inline, protected]</code></td></tr>
<tr class="memlist"><td><a class="el" href="classSigTermHandler.html#8f6c3da13e1ec7fc8ef122bd0db457e4">SigTermHandler</a>()</td><td><a class="el" href="classSigTermHandler.html">SigTermHandler</a></td><td><code> [inline]</code></td></tr>
<tr class="memlist"><td><a class="el" href="classSignalHandler.html#a1109d38f8b43bde75420aaeecc1f2b7">~SignalHandler</a>()</td><td><a class="el" href="classSignalHandler.html">SignalHandler</a></td><td><code> [inline, virtual]</code></td></tr>
-</table><hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+</table><hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/classSigTermHandler.html b/doc/html/classSigTermHandler.html
index 5ef407e..dc3abae 100644
--- a/doc/html/classSigTermHandler.html
+++ b/doc/html/classSigTermHandler.html
@@ -77,7 +77,7 @@ Reimplemented from <a class="el" href="classSignalHandler.html#e3dbda0de9b4aa454
</div><p>
<hr>The documentation for this class was generated from the following files:<ul>
<li><a class="el" href="signalController_8h-source.html">signalController.h</a><li><a class="el" href="signalController_8cpp.html">signalController.cpp</a></ul>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/classSigUsr1Handler-members.html b/doc/html/classSigUsr1Handler-members.html
index 59efb1f..6b73db0 100644
--- a/doc/html/classSigUsr1Handler-members.html
+++ b/doc/html/classSigUsr1Handler-members.html
@@ -23,7 +23,7 @@
<tr class="memlist"><td><a class="el" href="classSignalHandler.html#8f920534650e9cd3cdfbe3c3f8409b4d">SignalHandler</a>(int s)</td><td><a class="el" href="classSignalHandler.html">SignalHandler</a></td><td><code> [inline, protected]</code></td></tr>
<tr class="memlist"><td><a class="el" href="classSigUsr1Handler.html#aabaa57b0f2bb331a85f95cf90dd121d">SigUsr1Handler</a>()</td><td><a class="el" href="classSigUsr1Handler.html">SigUsr1Handler</a></td><td><code> [inline]</code></td></tr>
<tr class="memlist"><td><a class="el" href="classSignalHandler.html#a1109d38f8b43bde75420aaeecc1f2b7">~SignalHandler</a>()</td><td><a class="el" href="classSignalHandler.html">SignalHandler</a></td><td><code> [inline, virtual]</code></td></tr>
-</table><hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+</table><hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/classSigUsr1Handler.html b/doc/html/classSigUsr1Handler.html
index 364065f..795774d 100644
--- a/doc/html/classSigUsr1Handler.html
+++ b/doc/html/classSigUsr1Handler.html
@@ -77,7 +77,7 @@ Reimplemented from <a class="el" href="classSignalHandler.html#e3dbda0de9b4aa454
</div><p>
<hr>The documentation for this class was generated from the following files:<ul>
<li><a class="el" href="signalController_8h-source.html">signalController.h</a><li><a class="el" href="signalController_8cpp.html">signalController.cpp</a></ul>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/classSigUsr2Handler-members.html b/doc/html/classSigUsr2Handler-members.html
index 682f2c8..cb81e23 100644
--- a/doc/html/classSigUsr2Handler-members.html
+++ b/doc/html/classSigUsr2Handler-members.html
@@ -23,7 +23,7 @@
<tr class="memlist"><td><a class="el" href="classSignalHandler.html#8f920534650e9cd3cdfbe3c3f8409b4d">SignalHandler</a>(int s)</td><td><a class="el" href="classSignalHandler.html">SignalHandler</a></td><td><code> [inline, protected]</code></td></tr>
<tr class="memlist"><td><a class="el" href="classSigUsr2Handler.html#30478acdc28555b412d80f1419af622a">SigUsr2Handler</a>()</td><td><a class="el" href="classSigUsr2Handler.html">SigUsr2Handler</a></td><td><code> [inline]</code></td></tr>
<tr class="memlist"><td><a class="el" href="classSignalHandler.html#a1109d38f8b43bde75420aaeecc1f2b7">~SignalHandler</a>()</td><td><a class="el" href="classSignalHandler.html">SignalHandler</a></td><td><code> [inline, virtual]</code></td></tr>
-</table><hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+</table><hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/classSigUsr2Handler.html b/doc/html/classSigUsr2Handler.html
index 838e4f1..cfbf6d4 100644
--- a/doc/html/classSigUsr2Handler.html
+++ b/doc/html/classSigUsr2Handler.html
@@ -77,7 +77,7 @@ Reimplemented from <a class="el" href="classSignalHandler.html#e3dbda0de9b4aa454
</div><p>
<hr>The documentation for this class was generated from the following files:<ul>
<li><a class="el" href="signalController_8h-source.html">signalController.h</a><li><a class="el" href="signalController_8cpp.html">signalController.cpp</a></ul>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/classSignalController-members.html b/doc/html/classSignalController-members.html
index ab1a4c7..b491ebe 100644
--- a/doc/html/classSignalController-members.html
+++ b/doc/html/classSignalController-members.html
@@ -32,7 +32,7 @@
<tr class="memlist"><td><a class="el" href="classSignalController.html#4dfee82061341e1af5ca827333c8bd10">sigQueueSem</a></td><td><a class="el" href="classSignalController.html">SignalController</a></td><td><code> [private]</code></td></tr>
<tr class="memlist"><td><a class="el" href="classSignalController.html#79c5fbfa55aa9edc2a45c5ed3197b782">thread</a></td><td><a class="el" href="classSignalController.html">SignalController</a></td><td><code> [private]</code></td></tr>
<tr class="memlist"><td><a class="el" href="classSignalController.html#e8d687dc4fcc75bffff50e8cda37c7aa">~SignalController</a>()</td><td><a class="el" href="classSignalController.html">SignalController</a></td><td></td></tr>
-</table><hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+</table><hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/classSignalController.html b/doc/html/classSignalController.html
index a1fd372..459adc3 100644
--- a/doc/html/classSignalController.html
+++ b/doc/html/classSignalController.html
@@ -286,7 +286,7 @@
</div><p>
<hr>The documentation for this class was generated from the following files:<ul>
<li><a class="el" href="signalController_8h-source.html">signalController.h</a><li><a class="el" href="signalController_8cpp.html">signalController.cpp</a></ul>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/classSignalHandler-members.html b/doc/html/classSignalHandler-members.html
index 3daf736..707ea24 100644
--- a/doc/html/classSignalHandler-members.html
+++ b/doc/html/classSignalHandler-members.html
@@ -24,7 +24,7 @@
<tr class="memlist"><td><a class="el" href="classSignalHandler.html#8f920534650e9cd3cdfbe3c3f8409b4d">SignalHandler</a>(int s)</td><td><a class="el" href="classSignalHandler.html">SignalHandler</a></td><td><code> [inline, protected]</code></td></tr>
<tr class="memlist"><td><a class="el" href="classSignalHandler.html#0585573af0ea6bebf37bda54e5c3c39d">sigNum</a></td><td><a class="el" href="classSignalHandler.html">SignalHandler</a></td><td><code> [private]</code></td></tr>
<tr class="memlist"><td><a class="el" href="classSignalHandler.html#a1109d38f8b43bde75420aaeecc1f2b7">~SignalHandler</a>()</td><td><a class="el" href="classSignalHandler.html">SignalHandler</a></td><td><code> [inline, virtual]</code></td></tr>
-</table><hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+</table><hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/classSignalHandler.html b/doc/html/classSignalHandler.html
index 0ee449d..5538d9a 100644
--- a/doc/html/classSignalHandler.html
+++ b/doc/html/classSignalHandler.html
@@ -143,7 +143,7 @@ Reimplemented in <a class="el" href="classSigIntHandler.html#6a7d9a841a5c9b1f500
</div><p>
<hr>The documentation for this class was generated from the following file:<ul>
<li><a class="el" href="signalController_8h-source.html">signalController.h</a></ul>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/classSocket-members.html b/doc/html/classSocket-members.html
index 4a0ce9c..b1b072a 100644
--- a/doc/html/classSocket-members.html
+++ b/doc/html/classSocket-members.html
@@ -31,7 +31,7 @@
<tr class="memlist"><td><a class="el" href="classSocket.html#53e00027bab2125a2b407914c6148589">Socket</a>(int type, int protocol)</td><td><a class="el" href="classSocket.html">Socket</a></td><td><code> [protected]</code></td></tr>
<tr class="memlist"><td><a class="el" href="classSocket.html#6a2609eef6559336a595a336f138d395">Socket</a>(int sockDesc)</td><td><a class="el" href="classSocket.html">Socket</a></td><td><code> [protected]</code></td></tr>
<tr class="memlist"><td><a class="el" href="classSocket.html#eac4eb6379a543d38ed88977d3b6630a">~Socket</a>()</td><td><a class="el" href="classSocket.html">Socket</a></td><td></td></tr>
-</table><hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+</table><hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/classSocket.html b/doc/html/classSocket.html
index d94f825..a0a5587 100644
--- a/doc/html/classSocket.html
+++ b/doc/html/classSocket.html
@@ -378,7 +378,7 @@ Resolve the specified service for the specified protocol to the corresponding po
</div><p>
<hr>The documentation for this class was generated from the following files:<ul>
<li><a class="el" href="PracticalSocket_8h-source.html">PracticalSocket.h</a><li><a class="el" href="PracticalSocket_8cpp.html">PracticalSocket.cpp</a></ul>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/classSocketException-members.html b/doc/html/classSocketException-members.html
index 7518af8..7d1d8fa 100644
--- a/doc/html/classSocketException-members.html
+++ b/doc/html/classSocketException-members.html
@@ -23,7 +23,7 @@
<tr class="memlist"><td><a class="el" href="classSocketException.html#dcfeba6d4ce5754b48ae9d37b07a7e87">userMessage</a></td><td><a class="el" href="classSocketException.html">SocketException</a></td><td><code> [private]</code></td></tr>
<tr class="memlist"><td><a class="el" href="classSocketException.html#534b0625abe62cad2bae94758aa6eb42">what</a>() const</td><td><a class="el" href="classSocketException.html">SocketException</a></td><td></td></tr>
<tr class="memlist"><td><a class="el" href="classSocketException.html#659557c899329aea01977c980c4db9b9">~SocketException</a>()</td><td><a class="el" href="classSocketException.html">SocketException</a></td><td></td></tr>
-</table><hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+</table><hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/classSocketException.html b/doc/html/classSocketException.html
index cbb55b3..fb81446 100644
--- a/doc/html/classSocketException.html
+++ b/doc/html/classSocketException.html
@@ -130,7 +130,7 @@ Get the exception message <dl class="return" compact><dt><b>Returns:</b></dt><dd
</div><p>
<hr>The documentation for this class was generated from the following files:<ul>
<li><a class="el" href="PracticalSocket_8h-source.html">PracticalSocket.h</a><li><a class="el" href="PracticalSocket_8cpp.html">PracticalSocket.cpp</a></ul>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/classTCPServerSocket-members.html b/doc/html/classTCPServerSocket-members.html
index 4cb0a03..78fbbc6 100644
--- a/doc/html/classTCPServerSocket-members.html
+++ b/doc/html/classTCPServerSocket-members.html
@@ -33,7 +33,7 @@
<tr class="memlist"><td><a class="el" href="classTCPServerSocket.html#e559a3154527d09fe14a8e5ee1f53d7a">TCPServerSocket</a>(unsigned short localPort, int queueLen=5)</td><td><a class="el" href="classTCPServerSocket.html">TCPServerSocket</a></td><td></td></tr>
<tr class="memlist"><td><a class="el" href="classTCPServerSocket.html#3908fecb1b038f7c14fcc7726f54d01d">TCPServerSocket</a>(const string &amp;localAddress, unsigned short localPort, int queueLen=5)</td><td><a class="el" href="classTCPServerSocket.html">TCPServerSocket</a></td><td></td></tr>
<tr class="memlist"><td><a class="el" href="classSocket.html#eac4eb6379a543d38ed88977d3b6630a">~Socket</a>()</td><td><a class="el" href="classSocket.html">Socket</a></td><td></td></tr>
-</table><hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+</table><hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/classTCPServerSocket.html b/doc/html/classTCPServerSocket.html
index ad95c70..ae28527 100644
--- a/doc/html/classTCPServerSocket.html
+++ b/doc/html/classTCPServerSocket.html
@@ -177,7 +177,7 @@ Blocks until a new connection is established on this socket or error <dl class="
</div><p>
<hr>The documentation for this class was generated from the following files:<ul>
<li><a class="el" href="PracticalSocket_8h-source.html">PracticalSocket.h</a><li><a class="el" href="PracticalSocket_8cpp.html">PracticalSocket.cpp</a></ul>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/classTCPSocket-members.html b/doc/html/classTCPSocket-members.html
index d292b13..af641d0 100644
--- a/doc/html/classTCPSocket-members.html
+++ b/doc/html/classTCPSocket-members.html
@@ -40,7 +40,7 @@
<tr class="memlist"><td><a class="el" href="classTCPSocket.html#7b246b66f6dc3246ab2777b771e5f917">TCPSocket</a>(const string &amp;foreignAddress, unsigned short foreignPort)</td><td><a class="el" href="classTCPSocket.html">TCPSocket</a></td><td></td></tr>
<tr class="memlist"><td><a class="el" href="classTCPSocket.html#4763ac3be0d7d5e143884bef45e351c5">TCPSocket</a>(int newConnSD)</td><td><a class="el" href="classTCPSocket.html">TCPSocket</a></td><td><code> [private]</code></td></tr>
<tr class="memlist"><td><a class="el" href="classSocket.html#eac4eb6379a543d38ed88977d3b6630a">~Socket</a>()</td><td><a class="el" href="classSocket.html">Socket</a></td><td></td></tr>
-</table><hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+</table><hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/classTCPSocket.html b/doc/html/classTCPSocket.html
index beab093..0443d36 100644
--- a/doc/html/classTCPSocket.html
+++ b/doc/html/classTCPSocket.html
@@ -146,7 +146,7 @@ Construct a TCP socket with a connection to the given foreign address and port <
</div><p>
<hr>The documentation for this class was generated from the following files:<ul>
<li><a class="el" href="PracticalSocket_8h-source.html">PracticalSocket.h</a><li><a class="el" href="PracticalSocket_8cpp.html">PracticalSocket.cpp</a></ul>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/classTunDevice-members.html b/doc/html/classTunDevice-members.html
index a003776..6b64451 100644
--- a/doc/html/classTunDevice-members.html
+++ b/doc/html/classTunDevice-members.html
@@ -36,7 +36,7 @@
<tr class="memlist"><td><a class="el" href="classTunDevice.html#ec146b27c7755747c1cc1511e4482875">TYPE_UNDEF</a></td><td><a class="el" href="classTunDevice.html">TunDevice</a></td><td><code> [static]</code></td></tr>
<tr class="memlist"><td><a class="el" href="classTunDevice.html#958bc73a627cc5d404ed87204547134d">write</a>(Buffer &amp;buf)</td><td><a class="el" href="classTunDevice.html">TunDevice</a></td><td></td></tr>
<tr class="memlist"><td><a class="el" href="classTunDevice.html#2c6196d270bf4d0e99ff4f860391faed">~TunDevice</a>()</td><td><a class="el" href="classTunDevice.html">TunDevice</a></td><td></td></tr>
-</table><hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+</table><hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/classTunDevice.html b/doc/html/classTunDevice.html
index 9d7a1f2..4753ea7 100644
--- a/doc/html/classTunDevice.html
+++ b/doc/html/classTunDevice.html
@@ -395,7 +395,7 @@
</div><p>
<hr>The documentation for this class was generated from the following files:<ul>
<li><a class="el" href="tunDevice_8h-source.html">tunDevice.h</a><li><a class="el" href="tunDevice_8cpp.html">tunDevice.cpp</a></ul>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/classUDPPacketSource-members.html b/doc/html/classUDPPacketSource-members.html
index e66e52b..d02740e 100644
--- a/doc/html/classUDPPacketSource-members.html
+++ b/doc/html/classUDPPacketSource-members.html
@@ -51,7 +51,7 @@
<tr class="memlist"><td><a class="el" href="classUDPSocket.html#f19281c523f15ed30d7d78f09033713d">UDPSocket</a>(const string &amp;localAddress, unsigned short localPort)</td><td><a class="el" href="classUDPSocket.html">UDPSocket</a></td><td></td></tr>
<tr class="memlist"><td><a class="el" href="classPacketSource.html#fdaad665e453cf5a047935b07a050ef4">~PacketSource</a>()</td><td><a class="el" href="classPacketSource.html">PacketSource</a></td><td><code> [inline, virtual]</code></td></tr>
<tr class="memlist"><td><a class="el" href="classSocket.html#eac4eb6379a543d38ed88977d3b6630a">~Socket</a>()</td><td><a class="el" href="classSocket.html">Socket</a></td><td></td></tr>
-</table><hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+</table><hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/classUDPPacketSource.html b/doc/html/classUDPPacketSource.html
index 0ffe3d6..1326f09 100644
--- a/doc/html/classUDPPacketSource.html
+++ b/doc/html/classUDPPacketSource.html
@@ -188,7 +188,7 @@ Implements <a class="el" href="classPacketSource.html#ffc5eb2c89d1395443432c3cc6
</div><p>
<hr>The documentation for this class was generated from the following files:<ul>
<li><a class="el" href="packetSource_8h-source.html">packetSource.h</a><li><a class="el" href="packetSource_8cpp.html">packetSource.cpp</a></ul>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/classUDPSocket-members.html b/doc/html/classUDPSocket-members.html
index d418d43..49e8e41 100644
--- a/doc/html/classUDPSocket-members.html
+++ b/doc/html/classUDPSocket-members.html
@@ -46,7 +46,7 @@
<tr class="memlist"><td><a class="el" href="classUDPSocket.html#14dcb55c4b60b12d4a7fff648cbb825f">UDPSocket</a>(unsigned short localPort)</td><td><a class="el" href="classUDPSocket.html">UDPSocket</a></td><td></td></tr>
<tr class="memlist"><td><a class="el" href="classUDPSocket.html#f19281c523f15ed30d7d78f09033713d">UDPSocket</a>(const string &amp;localAddress, unsigned short localPort)</td><td><a class="el" href="classUDPSocket.html">UDPSocket</a></td><td></td></tr>
<tr class="memlist"><td><a class="el" href="classSocket.html#eac4eb6379a543d38ed88977d3b6630a">~Socket</a>()</td><td><a class="el" href="classSocket.html">Socket</a></td><td></td></tr>
-</table><hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+</table><hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/classUDPSocket.html b/doc/html/classUDPSocket.html
index d5d256d..4e63041 100644
--- a/doc/html/classUDPSocket.html
+++ b/doc/html/classUDPSocket.html
@@ -397,7 +397,7 @@ Leave the specified multicast group <dl compact><dt><b>Parameters:</b></dt><dd>
</div><p>
<hr>The documentation for this class was generated from the following files:<ul>
<li><a class="el" href="PracticalSocket_8h-source.html">PracticalSocket.h</a><li><a class="el" href="PracticalSocket_8cpp.html">PracticalSocket.cpp</a></ul>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/classsatp_1_1SATP-members.html b/doc/html/classsatp_1_1SATP-members.html
index 8fea2ca..51da390 100644
--- a/doc/html/classsatp_1_1SATP-members.html
+++ b/doc/html/classsatp_1_1SATP-members.html
@@ -65,7 +65,7 @@
<tr class="memlist"><td><a class="el" href="classPacket.html#ce9e40180f64d44fe1d8da14ac9e5df2">withHeader</a>(bool b)</td><td><a class="el" href="classPacket.html">Packet</a></td><td></td></tr>
<tr class="memlist"><td><a class="el" href="classPacket.html#c7ecfc05376afd00af89cb328e194a1d">withPayloadType</a>(bool b)</td><td><a class="el" href="classPacket.html">Packet</a></td><td></td></tr>
<tr class="memlist"><td><a class="el" href="classBuffer.html#59b8743e4a5f731bdd0c4185c9ef263b">~Buffer</a>()</td><td><a class="el" href="classBuffer.html">Buffer</a></td><td><code> [virtual]</code></td></tr>
-</table><hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+</table><hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/classsatp_1_1SATP.html b/doc/html/classsatp_1_1SATP.html
index bd53388..f95ae4a 100644
--- a/doc/html/classsatp_1_1SATP.html
+++ b/doc/html/classsatp_1_1SATP.html
@@ -71,7 +71,7 @@
</div><p>
<hr>The documentation for this class was generated from the following file:<ul>
<li><a class="el" href="satp_8py.html">satp.py</a></ul>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/cypher_8cpp.html b/doc/html/cypher_8cpp.html
index 488abec..74a61a7 100644
--- a/doc/html/cypher_8cpp.html
+++ b/doc/html/cypher_8cpp.html
@@ -26,7 +26,7 @@
<table border="0" cellpadding="0" cellspacing="0">
<tr><td></td></tr>
</table>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:24 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/cypher_8h-source.html b/doc/html/cypher_8h-source.html
index 31dd0f8..766e2a2 100644
--- a/doc/html/cypher_8h-source.html
+++ b/doc/html/cypher_8h-source.html
@@ -103,7 +103,7 @@
<a name="l00084"></a>00084
<a name="l00085"></a>00085
<a name="l00086"></a>00086 <span class="preprocessor">#endif</span>
-</pre></div><hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+</pre></div><hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:24 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/cypher_8h.html b/doc/html/cypher_8h.html
index 86fbb35..9638644 100644
--- a/doc/html/cypher_8h.html
+++ b/doc/html/cypher_8h.html
@@ -32,7 +32,7 @@
<tr><td class="memItemLeft" nowrap align="right" valign="top">class &nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="classAesIcmCypher.html">AesIcmCypher</a></td></tr>
</table>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:24 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/datatypes_8h-source.html b/doc/html/datatypes_8h-source.html
index 7d3684f..3d42f4c 100644
--- a/doc/html/datatypes_8h-source.html
+++ b/doc/html/datatypes_8h-source.html
@@ -81,7 +81,7 @@
<a name="l00062"></a><a class="code" href="datatypes_8h.html#e08ddfb4ec6d5f44e41d776eec5d6c4b">00062</a> <span class="preprocessor"></span><span class="preprocessor">#define AUTH_TAG_T_HTON(a) htonl(a)</span>
<a name="l00063"></a>00063 <span class="preprocessor"></span>
<a name="l00064"></a>00064 <span class="preprocessor">#endif</span>
-</pre></div><hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+</pre></div><hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:24 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/datatypes_8h.html b/doc/html/datatypes_8h.html
index 85180f6..94147ce 100644
--- a/doc/html/datatypes_8h.html
+++ b/doc/html/datatypes_8h.html
@@ -389,7 +389,7 @@
</div>
</div><p>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:24 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/files.html b/doc/html/files.html
index 8abd299..002ccd9 100644
--- a/doc/html/files.html
+++ b/doc/html/files.html
@@ -51,11 +51,13 @@
<tr><td class="indexkey"><a class="el" href="seqWindow_8h.html">seqWindow.h</a> <a href="seqWindow_8h-source.html">[code]</a></td><td class="indexvalue"></td></tr>
<tr><td class="indexkey"><a class="el" href="signalController_8cpp.html">signalController.cpp</a></td><td class="indexvalue"></td></tr>
<tr><td class="indexkey"><a class="el" href="signalController_8h.html">signalController.h</a> <a href="signalController_8h-source.html">[code]</a></td><td class="indexvalue"></td></tr>
+ <tr><td class="indexkey"><a class="el" href="syncSocket_8cpp.html">syncSocket.cpp</a></td><td class="indexvalue"></td></tr>
+ <tr><td class="indexkey"><a class="el" href="syncSocket_8h.html">syncSocket.h</a> <a href="syncSocket_8h-source.html">[code]</a></td><td class="indexvalue"></td></tr>
<tr><td class="indexkey"><a class="el" href="threadUtils_8hpp.html">threadUtils.hpp</a> <a href="threadUtils_8hpp-source.html">[code]</a></td><td class="indexvalue"></td></tr>
<tr><td class="indexkey"><a class="el" href="tunDevice_8cpp.html">tunDevice.cpp</a></td><td class="indexvalue"></td></tr>
<tr><td class="indexkey"><a class="el" href="tunDevice_8h.html">tunDevice.h</a> <a href="tunDevice_8h-source.html">[code]</a></td><td class="indexvalue"></td></tr>
</table>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/functions.html b/doc/html/functions.html
index 8492795..ab8af3e 100644
--- a/doc/html/functions.html
+++ b/doc/html/functions.html
@@ -62,7 +62,7 @@ Here is a list of all class members with links to the classes they belong to:
<li>__packed__
: <a class="el" href="classPacket.html#11b3534f67df6bb19963e6bc8090230b">Packet</a>
</ul>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/functions_0x61.html b/doc/html/functions_0x61.html
index 6c93fa4..9de59fc 100644
--- a/doc/html/functions_0x61.html
+++ b/doc/html/functions_0x61.html
@@ -83,7 +83,7 @@ Here is a list of all class members with links to the classes they belong to:
<li>AuthAlgo()
: <a class="el" href="classAuthAlgo.html#22a200c372d9aeb73a4cbdd95ba30a0e">AuthAlgo</a>
</ul>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/functions_0x62.html b/doc/html/functions_0x62.html
index a64fc9d..1b6731b 100644
--- a/doc/html/functions_0x62.html
+++ b/doc/html/functions_0x62.html
@@ -66,7 +66,7 @@ Here is a list of all class members with links to the classes they belong to:
<li>Buffer()
: <a class="el" href="classBuffer.html#042fe5bc1f8d0c25d5707d6955d1654c">Buffer</a>
</ul>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/functions_0x63.html b/doc/html/functions_0x63.html
index 26e65ce..84328c9 100644
--- a/doc/html/functions_0x63.html
+++ b/doc/html/functions_0x63.html
@@ -104,7 +104,7 @@ Here is a list of all class members with links to the classes they belong to:
<li>cypher_
: <a class="el" href="classOptions.html#bba16365a15a6a87c90f85e143bebb5f">Options</a>
</ul>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/functions_0x64.html b/doc/html/functions_0x64.html
index a466d47..415a82c 100644
--- a/doc/html/functions_0x64.html
+++ b/doc/html/functions_0x64.html
@@ -72,7 +72,7 @@ Here is a list of all class members with links to the classes they belong to:
<li>down()
: <a class="el" href="classSemaphore.html#71126a13a22f2722e22a2b69860a5371">Semaphore</a>
</ul>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/functions_0x65.html b/doc/html/functions_0x65.html
index 16aec5b..a6e32e8 100644
--- a/doc/html/functions_0x65.html
+++ b/doc/html/functions_0x65.html
@@ -64,7 +64,7 @@ Here is a list of all class members with links to the classes they belong to:
<li>exor()
: <a class="el" href="classCypher.html#bf33a7a59ed1cdf711030236de6635b0">Cypher</a>
</ul>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/functions_0x66.html b/doc/html/functions_0x66.html
index 03845f2..967a01c 100644
--- a/doc/html/functions_0x66.html
+++ b/doc/html/functions_0x66.html
@@ -102,7 +102,7 @@ Here is a list of all class members with links to the classes they belong to:
<li>fields_desc
: <a class="el" href="classsatp_1_1SATP.html#e51015e8537b5ec7aa53ba87bf638c15">satp::SATP</a>
</ul>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/functions_0x67.html b/doc/html/functions_0x67.html
index 2a03329..601f9fb 100644
--- a/doc/html/functions_0x67.html
+++ b/doc/html/functions_0x67.html
@@ -135,7 +135,7 @@ Here is a list of all class members with links to the classes they belong to:
<li>getTypeString()
: <a class="el" href="classTunDevice.html#eb99a885d90822b00e623ca02c2b06cc">TunDevice</a>
</ul>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/functions_0x68.html b/doc/html/functions_0x68.html
index 01eb7d1..254b8f6 100644
--- a/doc/html/functions_0x68.html
+++ b/doc/html/functions_0x68.html
@@ -87,7 +87,7 @@ Here is a list of all class members with links to the classes they belong to:
<li>hasSeqNr()
: <a class="el" href="classSeqWindow.html#9e7714dda181863420c38975bd505aff">SeqWindow</a>
</ul>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/functions_0x69.html b/doc/html/functions_0x69.html
index e883cf4..23010bd 100644
--- a/doc/html/functions_0x69.html
+++ b/doc/html/functions_0x69.html
@@ -83,7 +83,7 @@ Here is a list of all class members with links to the classes they belong to:
<li>isOpen()
: <a class="el" href="classTunDevice.html#f63f3331789f043e44eb435b78c815b2">TunDevice</a>
</ul>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/functions_0x6a.html b/doc/html/functions_0x6a.html
index 3f470b8..03ad19d 100644
--- a/doc/html/functions_0x6a.html
+++ b/doc/html/functions_0x6a.html
@@ -62,7 +62,7 @@ Here is a list of all class members with links to the classes they belong to:
<li>joinGroup()
: <a class="el" href="classUDPSocket.html#1b20c1e8bd49a9bd9b53dd4f1c8d4c11">UDPSocket</a>
</ul>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/functions_0x6b.html b/doc/html/functions_0x6b.html
index 1144abe..dcaf957 100644
--- a/doc/html/functions_0x6b.html
+++ b/doc/html/functions_0x6b.html
@@ -66,7 +66,7 @@ Here is a list of all class members with links to the classes they belong to:
<li>KeyDerivation()
: <a class="el" href="classKeyDerivation.html#07c3735d1b2e1285b6c427a2706ebc67">KeyDerivation</a>
</ul>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/functions_0x6c.html b/doc/html/functions_0x6c.html
index a8433c2..a0c9e1b 100644
--- a/doc/html/functions_0x6c.html
+++ b/doc/html/functions_0x6c.html
@@ -93,7 +93,7 @@ Here is a list of all class members with links to the classes they belong to:
, <a class="el" href="classLog.html#16ded253dbe65c503d1d853dcf5460d6">Log</a>
, <a class="el" href="classLogStringBuilder.html#5df8c8d7ab7615c8552de3d4d21d3417">LogStringBuilder</a>
</ul>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/functions_0x6d.html b/doc/html/functions_0x6d.html
index f36e03c..8386421 100644
--- a/doc/html/functions_0x6d.html
+++ b/doc/html/functions_0x6d.html
@@ -79,7 +79,7 @@ Here is a list of all class members with links to the classes they belong to:
, <a class="el" href="classSeqWindow.html#87ec44a9a7398ecbcb92d90ba95b37a0">SeqWindow</a>
, <a class="el" href="classConnectionList.html#bc652277cdcea45e22a0b5a8fc23ef48">ConnectionList</a>
</ul>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/functions_0x6e.html b/doc/html/functions_0x6e.html
index f83e93c..778be7a 100644
--- a/doc/html/functions_0x6e.html
+++ b/doc/html/functions_0x6e.html
@@ -66,7 +66,7 @@ Here is a list of all class members with links to the classes they belong to:
<li>NetworkAddress()
: <a class="el" href="classNetworkAddress.html#453e23f7a4cbaebfa0ab799a5e01d02c">NetworkAddress</a>
</ul>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/functions_0x6f.html b/doc/html/functions_0x6f.html
index dd8a022..db9fab5 100644
--- a/doc/html/functions_0x6f.html
+++ b/doc/html/functions_0x6f.html
@@ -59,6 +59,12 @@
Here is a list of all class members with links to the classes they belong to:
<p>
<h3><a class="anchor" name="index_o">- o -</a></h3><ul>
+<li>OnAccept()
+: <a class="el" href="classSyncSocket.html#682c668b65bfa3c59e7628c3f29f49ae">SyncSocket</a>
+<li>OnConnectRetry()
+: <a class="el" href="classSyncSocket.html#9884cf2e14e1c38607e58ba62c59c44f">SyncSocket</a>
+<li>OnReconnect()
+: <a class="el" href="classSyncSocket.html#cf37b4f2726ce657a0472f55c915fd09">SyncSocket</a>
<li>open()
: <a class="el" href="classLog.html#f91976ebadd955414799131cb442d24c">Log</a>
, <a class="el" href="classTunDevice.html#323ddcfd4ac60d0dbfe6ebb5bbb9a323">TunDevice</a>
@@ -70,17 +76,16 @@ Here is a list of all class members with links to the classes they belong to:
: <a class="el" href="classLogStringBuilder.html#9b4f26f5e64aacc172c0818073117e42">LogStringBuilder</a>
<li>operator=()
: <a class="el" href="classSignalController.html#7bfe78f3e8c5d40ddd51c313d30cf6a2">SignalController</a>
-, <a class="el" href="classMutex.html#030a11400d00ef97813c6b232a5e3f43">Mutex</a>
, <a class="el" href="classBuffer.html#b62dfbb5605a860aa63771f3b1c29b1e">Buffer</a>
, <a class="el" href="classSocket.html#1ef8f4c222c32756c8b1537323702df8">Socket</a>
, <a class="el" href="classRouter.html#58551e8a03d9d30a1047d5859ecf6895">Router</a>
, <a class="el" href="classSeqWindow.html#37887e66297163fe301c77f2977a2a2b">SeqWindow</a>
-, <a class="el" href="classTunDevice.html#de33e9a7a951b43f2f7e24d8fe9c311e">TunDevice</a>
-, <a class="el" href="classConnectionList.html#b5ca2cf9bb5a4079d5c634a89ece1204">ConnectionList</a>
-, <a class="el" href="classBuffer.html#14cec0d3bf4f3f1a4a9930a8c53eb43a">Buffer</a>
, <a class="el" href="classLock.html#6beb534a89b213d70e4b3bb9b3cde217">Lock</a>
+, <a class="el" href="classTunDevice.html#de33e9a7a951b43f2f7e24d8fe9c311e">TunDevice</a>
, <a class="el" href="classLog.html#076b147c2bc9b2167074e9bc51a24af7">Log</a>
+, <a class="el" href="classConnectionList.html#b5ca2cf9bb5a4079d5c634a89ece1204">ConnectionList</a>
, <a class="el" href="classBuffer.html#b3bda89f495b3895a533155f593ab503">Buffer</a>
+, <a class="el" href="classMutex.html#030a11400d00ef97813c6b232a5e3f43">Mutex</a>
<li>operator[]()
: <a class="el" href="classBuffer.html#e5a9559862374ebd9dfcfc1204890497">Buffer</a>
<li>operator^()
@@ -92,7 +97,7 @@ Here is a list of all class members with links to the classes they belong to:
<li>Options()
: <a class="el" href="classOptions.html#b72fb640172a6109e34c8a5366563753">Options</a>
</ul>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/functions_0x70.html b/doc/html/functions_0x70.html
index e2bf677..2422d5e 100644
--- a/doc/html/functions_0x70.html
+++ b/doc/html/functions_0x70.html
@@ -90,7 +90,7 @@ Here is a list of all class members with links to the classes they belong to:
<li>progname_
: <a class="el" href="classOptions.html#aed7d0eeae21d7d00eb35dccea48b9f3">Options</a>
</ul>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/functions_0x72.html b/doc/html/functions_0x72.html
index 8492021..8f77018 100644
--- a/doc/html/functions_0x72.html
+++ b/doc/html/functions_0x72.html
@@ -90,7 +90,7 @@ Here is a list of all class members with links to the classes they belong to:
<li>run()
: <a class="el" href="classSignalController.html#0f7657b70cb2e8457539d9f844a93619">SignalController</a>
</ul>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/functions_0x73.html b/doc/html/functions_0x73.html
index ffcd0c2..a93c1c8 100644
--- a/doc/html/functions_0x73.html
+++ b/doc/html/functions_0x73.html
@@ -180,15 +180,17 @@ Here is a list of all class members with links to the classes they belong to:
<li>sockDesc
: <a class="el" href="classSocket.html#d5704d2fdfb062139e1f88831617bbfb">Socket</a>
<li>Socket()
-: <a class="el" href="classSocket.html#656389d58fa00729ff70c4e159623f5c">Socket</a>
+: <a class="el" href="classSocket.html#53e00027bab2125a2b407914c6148589">Socket</a>
<li>SocketException()
: <a class="el" href="classSocketException.html#bb5bcecd9d9e20868c237ec5a82cf5c3">SocketException</a>
<li>src
: <a class="el" href="structParam.html#fa5715cd7dc0833ea8f9afcbd1db455c">Param</a>
<li>stream
: <a class="el" href="classLogStringBuilder.html#405447561d3d7337cc093dad6c6d81b5">LogStringBuilder</a>
+<li>SyncSocket()
+: <a class="el" href="classSyncSocket.html#b97696932793f048f29e279f356ee6c5">SyncSocket</a>
</ul>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/functions_0x74.html b/doc/html/functions_0x74.html
index 6c1f8ad..5e15c67 100644
--- a/doc/html/functions_0x74.html
+++ b/doc/html/functions_0x74.html
@@ -76,7 +76,7 @@ Here is a list of all class members with links to the classes they belong to:
<li>TYPE_UNDEF
: <a class="el" href="classTunDevice.html#ec146b27c7755747c1cc1511e4482875">TunDevice</a>
</ul>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/functions_0x75.html b/doc/html/functions_0x75.html
index 5a00f5b..bb25909 100644
--- a/doc/html/functions_0x75.html
+++ b/doc/html/functions_0x75.html
@@ -71,7 +71,7 @@ Here is a list of all class members with links to the classes they belong to:
<li>userMessage
: <a class="el" href="classSocketException.html#dcfeba6d4ce5754b48ae9d37b07a7e87">SocketException</a>
</ul>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/functions_0x77.html b/doc/html/functions_0x77.html
index 91d5d8f..e43cf3c 100644
--- a/doc/html/functions_0x77.html
+++ b/doc/html/functions_0x77.html
@@ -74,7 +74,7 @@ Here is a list of all class members with links to the classes they belong to:
<li>write()
: <a class="el" href="classTunDevice.html#958bc73a627cc5d404ed87204547134d">TunDevice</a>
</ul>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/functions_0x7e.html b/doc/html/functions_0x7e.html
index bf6c893..5bfa655 100644
--- a/doc/html/functions_0x7e.html
+++ b/doc/html/functions_0x7e.html
@@ -104,7 +104,7 @@ Here is a list of all class members with links to the classes they belong to:
<li>~TunDevice()
: <a class="el" href="classTunDevice.html#2c6196d270bf4d0e99ff4f860391faed">TunDevice</a>
</ul>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/functions_func.html b/doc/html/functions_func.html
index 9fb75a8..8fc1770 100644
--- a/doc/html/functions_func.html
+++ b/doc/html/functions_func.html
@@ -75,7 +75,7 @@
<li>AuthAlgo()
: <a class="el" href="classAuthAlgo.html#22a200c372d9aeb73a4cbdd95ba30a0e">AuthAlgo</a>
</ul>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/functions_func_0x62.html b/doc/html/functions_func_0x62.html
index 2128368..e911008 100644
--- a/doc/html/functions_func_0x62.html
+++ b/doc/html/functions_func_0x62.html
@@ -62,7 +62,7 @@
<li>Buffer()
: <a class="el" href="classBuffer.html#5c58aa9e491f709011408ee7837d57d0">Buffer</a>
</ul>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/functions_func_0x63.html b/doc/html/functions_func_0x63.html
index eb4a939..d6ef957 100644
--- a/doc/html/functions_func_0x63.html
+++ b/doc/html/functions_func_0x63.html
@@ -85,7 +85,7 @@
<li>Cypher()
: <a class="el" href="classCypher.html#5228228b0b2d83251ecce4516e87ddb1">Cypher</a>
</ul>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/functions_func_0x64.html b/doc/html/functions_func_0x64.html
index d10502b..722fb0b 100644
--- a/doc/html/functions_func_0x64.html
+++ b/doc/html/functions_func_0x64.html
@@ -62,7 +62,7 @@
<li>down()
: <a class="el" href="classSemaphore.html#71126a13a22f2722e22a2b69860a5371">Semaphore</a>
</ul>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/functions_func_0x65.html b/doc/html/functions_func_0x65.html
index 85badbc..f20e00c 100644
--- a/doc/html/functions_func_0x65.html
+++ b/doc/html/functions_func_0x65.html
@@ -60,7 +60,7 @@
<li>exor()
: <a class="el" href="classCypher.html#bf33a7a59ed1cdf711030236de6635b0">Cypher</a>
</ul>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/functions_func_0x67.html b/doc/html/functions_func_0x67.html
index aae0203..bee54f4 100644
--- a/doc/html/functions_func_0x67.html
+++ b/doc/html/functions_func_0x67.html
@@ -129,7 +129,7 @@
<li>getTypeString()
: <a class="el" href="classTunDevice.html#eb99a885d90822b00e623ca02c2b06cc">TunDevice</a>
</ul>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/functions_func_0x68.html b/doc/html/functions_func_0x68.html
index 2cb5ac8..1d580de 100644
--- a/doc/html/functions_func_0x68.html
+++ b/doc/html/functions_func_0x68.html
@@ -75,7 +75,7 @@
<li>hasSeqNr()
: <a class="el" href="classSeqWindow.html#9e7714dda181863420c38975bd505aff">SeqWindow</a>
</ul>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/functions_func_0x69.html b/doc/html/functions_func_0x69.html
index 4da87b1..1cfff83 100644
--- a/doc/html/functions_func_0x69.html
+++ b/doc/html/functions_func_0x69.html
@@ -65,7 +65,7 @@
<li>isOpen()
: <a class="el" href="classTunDevice.html#f63f3331789f043e44eb435b78c815b2">TunDevice</a>
</ul>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/functions_func_0x6a.html b/doc/html/functions_func_0x6a.html
index 6d20b15..81982c5 100644
--- a/doc/html/functions_func_0x6a.html
+++ b/doc/html/functions_func_0x6a.html
@@ -60,7 +60,7 @@
<li>joinGroup()
: <a class="el" href="classUDPSocket.html#1b20c1e8bd49a9bd9b53dd4f1c8d4c11">UDPSocket</a>
</ul>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/functions_func_0x6b.html b/doc/html/functions_func_0x6b.html
index 58bccb3..36b2ab6 100644
--- a/doc/html/functions_func_0x6b.html
+++ b/doc/html/functions_func_0x6b.html
@@ -60,7 +60,7 @@
<li>KeyDerivation()
: <a class="el" href="classKeyDerivation.html#07c3735d1b2e1285b6c427a2706ebc67">KeyDerivation</a>
</ul>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/functions_func_0x6c.html b/doc/html/functions_func_0x6c.html
index d5884a0..50e635f 100644
--- a/doc/html/functions_func_0x6c.html
+++ b/doc/html/functions_func_0x6c.html
@@ -70,7 +70,7 @@
<li>LogStringBuilder()
: <a class="el" href="classLogStringBuilder.html#a9393394f93ca644c8a851fb8fe04e24">LogStringBuilder</a>
</ul>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/functions_func_0x6d.html b/doc/html/functions_func_0x6d.html
index 315795a..d514da8 100644
--- a/doc/html/functions_func_0x6d.html
+++ b/doc/html/functions_func_0x6d.html
@@ -62,7 +62,7 @@
<li>Mutex()
: <a class="el" href="classMutex.html#7f1ad3a125c7a02b2ca338240bd1d978">Mutex</a>
</ul>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/functions_func_0x6f.html b/doc/html/functions_func_0x6f.html
index fc785e3..a30d609 100644
--- a/doc/html/functions_func_0x6f.html
+++ b/doc/html/functions_func_0x6f.html
@@ -57,6 +57,12 @@
&nbsp;
<p>
<h3><a class="anchor" name="index_o">- o -</a></h3><ul>
+<li>OnAccept()
+: <a class="el" href="classSyncSocket.html#682c668b65bfa3c59e7628c3f29f49ae">SyncSocket</a>
+<li>OnConnectRetry()
+: <a class="el" href="classSyncSocket.html#9884cf2e14e1c38607e58ba62c59c44f">SyncSocket</a>
+<li>OnReconnect()
+: <a class="el" href="classSyncSocket.html#cf37b4f2726ce657a0472f55c915fd09">SyncSocket</a>
<li>open()
: <a class="el" href="classLog.html#f91976ebadd955414799131cb442d24c">Log</a>
, <a class="el" href="classTunDevice.html#323ddcfd4ac60d0dbfe6ebb5bbb9a323">TunDevice</a>
@@ -67,17 +73,16 @@
<li>operator&lt;&lt;()
: <a class="el" href="classLogStringBuilder.html#9b4f26f5e64aacc172c0818073117e42">LogStringBuilder</a>
<li>operator=()
-: <a class="el" href="classSignalController.html#7bfe78f3e8c5d40ddd51c313d30cf6a2">SignalController</a>
-, <a class="el" href="classMutex.html#030a11400d00ef97813c6b232a5e3f43">Mutex</a>
+: <a class="el" href="classConnectionList.html#b5ca2cf9bb5a4079d5c634a89ece1204">ConnectionList</a>
+, <a class="el" href="classSeqWindow.html#37887e66297163fe301c77f2977a2a2b">SeqWindow</a>
, <a class="el" href="classRouter.html#58551e8a03d9d30a1047d5859ecf6895">Router</a>
, <a class="el" href="classSocket.html#1ef8f4c222c32756c8b1537323702df8">Socket</a>
-, <a class="el" href="classBuffer.html#b62dfbb5605a860aa63771f3b1c29b1e">Buffer</a>
-, <a class="el" href="classSeqWindow.html#37887e66297163fe301c77f2977a2a2b">SeqWindow</a>
-, <a class="el" href="classLog.html#076b147c2bc9b2167074e9bc51a24af7">Log</a>
-, <a class="el" href="classConnectionList.html#b5ca2cf9bb5a4079d5c634a89ece1204">ConnectionList</a>
+, <a class="el" href="classSignalController.html#7bfe78f3e8c5d40ddd51c313d30cf6a2">SignalController</a>
, <a class="el" href="classTunDevice.html#de33e9a7a951b43f2f7e24d8fe9c311e">TunDevice</a>
, <a class="el" href="classLock.html#6beb534a89b213d70e4b3bb9b3cde217">Lock</a>
-, <a class="el" href="classBuffer.html#b3bda89f495b3895a533155f593ab503">Buffer</a>
+, <a class="el" href="classLog.html#076b147c2bc9b2167074e9bc51a24af7">Log</a>
+, <a class="el" href="classMutex.html#030a11400d00ef97813c6b232a5e3f43">Mutex</a>
+, <a class="el" href="classBuffer.html#b62dfbb5605a860aa63771f3b1c29b1e">Buffer</a>
<li>operator[]()
: <a class="el" href="classBuffer.html#763882c627db10206f78b090556b00fa">Buffer</a>
<li>operator^()
@@ -85,7 +90,7 @@
<li>Options()
: <a class="el" href="classOptions.html#b72fb640172a6109e34c8a5366563753">Options</a>
</ul>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/functions_func_0x70.html b/doc/html/functions_func_0x70.html
index 2355fe7..69aadc5 100644
--- a/doc/html/functions_func_0x70.html
+++ b/doc/html/functions_func_0x70.html
@@ -68,7 +68,7 @@
<li>printUsage()
: <a class="el" href="classOptions.html#5a64af47966f3c0a54a8c3a3385065e3">Options</a>
</ul>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/functions_func_0x72.html b/doc/html/functions_func_0x72.html
index fd24ca3..2d33f96 100644
--- a/doc/html/functions_func_0x72.html
+++ b/doc/html/functions_func_0x72.html
@@ -84,7 +84,7 @@
<li>run()
: <a class="el" href="classSignalController.html#0f7657b70cb2e8457539d9f844a93619">SignalController</a>
</ul>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/functions_func_0x73.html b/doc/html/functions_func_0x73.html
index 86822b3..3a129e3 100644
--- a/doc/html/functions_func_0x73.html
+++ b/doc/html/functions_func_0x73.html
@@ -144,11 +144,13 @@
<li>SigUsr2Handler()
: <a class="el" href="classSigUsr2Handler.html#30478acdc28555b412d80f1419af622a">SigUsr2Handler</a>
<li>Socket()
-: <a class="el" href="classSocket.html#656389d58fa00729ff70c4e159623f5c">Socket</a>
+: <a class="el" href="classSocket.html#53e00027bab2125a2b407914c6148589">Socket</a>
<li>SocketException()
: <a class="el" href="classSocketException.html#bb5bcecd9d9e20868c237ec5a82cf5c3">SocketException</a>
+<li>SyncSocket()
+: <a class="el" href="classSyncSocket.html#b97696932793f048f29e279f356ee6c5">SyncSocket</a>
</ul>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/functions_func_0x74.html b/doc/html/functions_func_0x74.html
index 702be39..5bb1114 100644
--- a/doc/html/functions_func_0x74.html
+++ b/doc/html/functions_func_0x74.html
@@ -64,7 +64,7 @@
<li>TunDevice()
: <a class="el" href="classTunDevice.html#4587b54228b4240334ad4614211df394">TunDevice</a>
</ul>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/functions_func_0x75.html b/doc/html/functions_func_0x75.html
index 5722f55..4af2a72 100644
--- a/doc/html/functions_func_0x75.html
+++ b/doc/html/functions_func_0x75.html
@@ -66,7 +66,7 @@
<li>up()
: <a class="el" href="classSemaphore.html#15fb190263808234fc2562f39f523082">Semaphore</a>
</ul>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/functions_func_0x77.html b/doc/html/functions_func_0x77.html
index 04dd520..37e9e32 100644
--- a/doc/html/functions_func_0x77.html
+++ b/doc/html/functions_func_0x77.html
@@ -70,7 +70,7 @@
<li>write()
: <a class="el" href="classTunDevice.html#958bc73a627cc5d404ed87204547134d">TunDevice</a>
</ul>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/functions_func_0x7e.html b/doc/html/functions_func_0x7e.html
index 25e5e92..6d326f2 100644
--- a/doc/html/functions_func_0x7e.html
+++ b/doc/html/functions_func_0x7e.html
@@ -102,7 +102,7 @@
<li>~TunDevice()
: <a class="el" href="classTunDevice.html#2c6196d270bf4d0e99ff4f860391faed">TunDevice</a>
</ul>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/functions_rela.html b/doc/html/functions_rela.html
index d61ae8c..03806c3 100644
--- a/doc/html/functions_rela.html
+++ b/doc/html/functions_rela.html
@@ -47,7 +47,7 @@
<li>UDPPacketSource
: <a class="el" href="classBuffer.html#940a382a5e3a8622e6689e13dc453481">Buffer</a>
</ul>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/functions_type.html b/doc/html/functions_type.html
index 9f51a89..9a47f7c 100644
--- a/doc/html/functions_type.html
+++ b/doc/html/functions_type.html
@@ -39,7 +39,7 @@
<li>SeqDeque
: <a class="el" href="classSeqWindow.html#cf2d07003c8ca868146cffb4dd1d5ca7">SeqWindow</a>
</ul>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/functions_vars.html b/doc/html/functions_vars.html
index 496da68..c5a6aa9 100644
--- a/doc/html/functions_vars.html
+++ b/doc/html/functions_vars.html
@@ -312,7 +312,7 @@
<li>window_size_
: <a class="el" href="classSeqWindow.html#ef85ba28f8a655dc8c8d34aeddb8eea0">SeqWindow</a>
</ul>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/globals.html b/doc/html/globals.html
index 5b6400a..c90093c 100644
--- a/doc/html/globals.html
+++ b/doc/html/globals.html
@@ -141,6 +141,8 @@ Here is a list of all file members with links to the files they belong to:
: <a class="el" href="datatypes_8h.html#18c9cf2c5be6cb1e16a319a4da44989b">datatypes.h</a>
<li>SEQ_NR_T_NTOH
: <a class="el" href="datatypes_8h.html#4c349b0b408b8f654c8713c205f33f60">datatypes.h</a>
+<li>sync_receiver()
+: <a class="el" href="anytun_8cpp.html#4fd43e7c243b1cc78c583a915dfd4d55">anytun.cpp</a>
</ul>
<h3><a class="anchor" name="index_u">- u -</a></h3><ul>
<li>u_int16_t
@@ -154,7 +156,7 @@ Here is a list of all file members with links to the files they belong to:
<li>window_size_t
: <a class="el" href="datatypes_8h.html#0246b9fac0b861d94e0e4cc9ae2e5070">datatypes.h</a>
</ul>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/globals_defs.html b/doc/html/globals_defs.html
index 0e7b7fc..9fc1ae9 100644
--- a/doc/html/globals_defs.html
+++ b/doc/html/globals_defs.html
@@ -60,7 +60,7 @@
<li>SEQ_NR_T_NTOH
: <a class="el" href="datatypes_8h.html#4c349b0b408b8f654c8713c205f33f60">datatypes.h</a>
</ul>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/globals_enum.html b/doc/html/globals_enum.html
index 71b1241..3e6ba95 100644
--- a/doc/html/globals_enum.html
+++ b/doc/html/globals_enum.html
@@ -36,7 +36,7 @@
<li>satp_prf_label
: <a class="el" href="keyDerivation_8h.html#4829fcd87054af9b3ced79bbac1ce1eb">keyDerivation.h</a>
</ul>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/globals_eval.html b/doc/html/globals_eval.html
index 5e37894..ae49325 100644
--- a/doc/html/globals_eval.html
+++ b/doc/html/globals_eval.html
@@ -44,7 +44,7 @@
<li>label_satp_salt
: <a class="el" href="keyDerivation_8h.html#4829fcd87054af9b3ced79bbac1ce1eb78eb4c963e5ca87676c0a713e2fd9aa4">keyDerivation.h</a>
</ul>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/globals_func.html b/doc/html/globals_func.html
index e725d85..90b25d4 100644
--- a/doc/html/globals_func.html
+++ b/doc/html/globals_func.html
@@ -39,8 +39,10 @@
: <a class="el" href="anytun_8cpp.html#1a93139691e3d8cf8a996c973c5ca0ac">anytun.cpp</a>
<li>sender()
: <a class="el" href="anytun_8cpp.html#0f2bdeb94d90f5229b9e904e592b24fd">anytun.cpp</a>
+<li>sync_receiver()
+: <a class="el" href="anytun_8cpp.html#4fd43e7c243b1cc78c583a915dfd4d55">anytun.cpp</a>
</ul>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/globals_type.html b/doc/html/globals_type.html
index 2737b06..d8eaed3 100644
--- a/doc/html/globals_type.html
+++ b/doc/html/globals_type.html
@@ -56,7 +56,7 @@
<li>window_size_t
: <a class="el" href="datatypes_8h.html#0246b9fac0b861d94e0e4cc9ae2e5070">datatypes.h</a>
</ul>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/globals_vars.html b/doc/html/globals_vars.html
index 8ff69c2..798de5e 100644
--- a/doc/html/globals_vars.html
+++ b/doc/html/globals_vars.html
@@ -35,7 +35,7 @@
: <a class="el" href="log_8cpp.html#dabafeab912880de79e232735f44ce33">log.cpp</a>
, <a class="el" href="log_8h.html#dabafeab912880de79e232735f44ce33">log.h</a>
</ul>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/hierarchy.html b/doc/html/hierarchy.html
index 62c9279..adabb7e 100644
--- a/doc/html/hierarchy.html
+++ b/doc/html/hierarchy.html
@@ -79,9 +79,10 @@
<li><a class="el" href="classTCPServerSocket.html">TCPServerSocket</a>
</ul>
<li><a class="el" href="classSocketException.html">SocketException</a>
+<li><a class="el" href="classSyncSocket.html">SyncSocket</a>
<li><a class="el" href="classTunDevice.html">TunDevice</a>
</ul>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/keyDerivation_8cpp.html b/doc/html/keyDerivation_8cpp.html
index 28824d7..5ef5a9f 100644
--- a/doc/html/keyDerivation_8cpp.html
+++ b/doc/html/keyDerivation_8cpp.html
@@ -25,7 +25,7 @@
<table border="0" cellpadding="0" cellspacing="0">
<tr><td></td></tr>
</table>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:24 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/keyDerivation_8h-source.html b/doc/html/keyDerivation_8h-source.html
index 1d44ebb..c21f190 100644
--- a/doc/html/keyDerivation_8h-source.html
+++ b/doc/html/keyDerivation_8h-source.html
@@ -88,7 +88,7 @@
<a name="l00069"></a>00069
<a name="l00070"></a>00070 <span class="preprocessor">#endif</span>
<a name="l00071"></a>00071 <span class="preprocessor"></span>
-</pre></div><hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+</pre></div><hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:24 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/keyDerivation_8h.html b/doc/html/keyDerivation_8h.html
index e6d8555..9b3d465 100644
--- a/doc/html/keyDerivation_8h.html
+++ b/doc/html/keyDerivation_8h.html
@@ -60,7 +60,7 @@
</div>
</div><p>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/log_8cpp.html b/doc/html/log_8cpp.html
index 1fc383e..458340e 100644
--- a/doc/html/log_8cpp.html
+++ b/doc/html/log_8cpp.html
@@ -44,7 +44,7 @@
</div>
</div><p>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/log_8h-source.html b/doc/html/log_8h-source.html
index 0befeae..8a31ca2 100644
--- a/doc/html/log_8h-source.html
+++ b/doc/html/log_8h-source.html
@@ -143,7 +143,7 @@
<a name="l00124"></a>00124 <span class="keyword">extern</span> <a class="code" href="classLog.html">Log</a>&amp; <a class="code" href="log_8cpp.html#dabafeab912880de79e232735f44ce33">cLog</a>;
<a name="l00125"></a>00125
<a name="l00126"></a>00126 <span class="preprocessor">#endif</span>
-</pre></div><hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+</pre></div><hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:24 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/log_8h.html b/doc/html/log_8h.html
index 16d6325..d19f0f5 100644
--- a/doc/html/log_8h.html
+++ b/doc/html/log_8h.html
@@ -52,7 +52,7 @@
</div>
</div><p>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/main.html b/doc/html/main.html
index 19fdeec..a996f47 100644
--- a/doc/html/main.html
+++ b/doc/html/main.html
@@ -14,7 +14,7 @@
</ul></div>
<h1>anytun Documentation</h1>
<p>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:24 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/namespaces.html b/doc/html/namespaces.html
index 4947ec3..317480d 100644
--- a/doc/html/namespaces.html
+++ b/doc/html/namespaces.html
@@ -15,9 +15,10 @@
<h1>anytun Namespace List</h1>Here is a list of all namespaces with brief descriptions:<table>
<tr><td class="indexkey"><a class="el" href="namespacesatp.html">satp</a></td><td class="indexvalue"></td></tr>
<tr><td class="indexkey"><a class="el" href="namespacescapy_1_1_5.html">scapy::*</a></td><td class="indexvalue"></td></tr>
+ <tr><td class="indexkey"><a class="el" href="namespacesockets.html">sockets</a></td><td class="indexvalue"></td></tr>
<tr><td class="indexkey"><a class="el" href="namespacestd.html">std</a></td><td class="indexvalue"></td></tr>
</table>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/namespacesatp.html b/doc/html/namespacesatp.html
index 6bd7ede..7350ea2 100644
--- a/doc/html/namespacesatp.html
+++ b/doc/html/namespacesatp.html
@@ -20,7 +20,7 @@
<tr><td class="memItemLeft" nowrap align="right" valign="top">class &nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="classsatp_1_1SATP.html">SATP</a></td></tr>
</table>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/namespacescapy_1_1_5.html b/doc/html/namespacescapy_1_1_5.html
index d4856bf..35f8937 100644
--- a/doc/html/namespacescapy_1_1_5.html
+++ b/doc/html/namespacescapy_1_1_5.html
@@ -17,7 +17,7 @@
<table border="0" cellpadding="0" cellspacing="0">
<tr><td></td></tr>
</table>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/namespacestd.html b/doc/html/namespacestd.html
index b169d2c..9221963 100644
--- a/doc/html/namespacestd.html
+++ b/doc/html/namespacestd.html
@@ -17,7 +17,7 @@
<table border="0" cellpadding="0" cellspacing="0">
<tr><td></td></tr>
</table>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/options_8cpp.html b/doc/html/options_8cpp.html
index d8c6be1..55dc4ca 100644
--- a/doc/html/options_8cpp.html
+++ b/doc/html/options_8cpp.html
@@ -168,7 +168,7 @@
</pre></div>
</div>
</div><p>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/options_8h-source.html b/doc/html/options_8h-source.html
index 5af88be..0462740 100644
--- a/doc/html/options_8h-source.html
+++ b/doc/html/options_8h-source.html
@@ -114,7 +114,7 @@
<a name="l00095"></a>00095 };
<a name="l00096"></a>00096
<a name="l00097"></a>00097 <span class="preprocessor">#endif</span>
-</pre></div><hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+</pre></div><hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:24 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/options_8h.html b/doc/html/options_8h.html
index 04d0e65..5cea566 100644
--- a/doc/html/options_8h.html
+++ b/doc/html/options_8h.html
@@ -27,7 +27,7 @@
<tr><td class="memItemLeft" nowrap align="right" valign="top">class &nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="classOptions.html">Options</a></td></tr>
</table>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/packetSource_8cpp.html b/doc/html/packetSource_8cpp.html
index 650e74b..2615f04 100644
--- a/doc/html/packetSource_8cpp.html
+++ b/doc/html/packetSource_8cpp.html
@@ -24,7 +24,7 @@
<table border="0" cellpadding="0" cellspacing="0">
<tr><td></td></tr>
</table>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/packetSource_8h-source.html b/doc/html/packetSource_8h-source.html
index 9096246..8bb8151 100644
--- a/doc/html/packetSource_8h-source.html
+++ b/doc/html/packetSource_8h-source.html
@@ -71,7 +71,7 @@
<a name="l00052"></a>00052 <span class="keywordtype">void</span> <a class="code" href="classUDPPacketSource.html#376a3b0c861aeb7561e8a9f6866292b9">send</a>(<a class="code" href="classBuffer.html">Buffer</a>&amp; buf, std::string addr, <a class="code" href="datatypes_8h.html#3aa89f830bb876725b238e6a2a67a809">u_int16_t</a> port);
<a name="l00053"></a>00053 };
<a name="l00054"></a>00054
-</pre></div><hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+</pre></div><hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:24 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/packetSource_8h.html b/doc/html/packetSource_8h.html
index 115d9ee..afc9c47 100644
--- a/doc/html/packetSource_8h.html
+++ b/doc/html/packetSource_8h.html
@@ -30,7 +30,7 @@
<tr><td class="memItemLeft" nowrap align="right" valign="top">class &nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="classUDPPacketSource.html">UDPPacketSource</a></td></tr>
</table>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/packet_8cpp.html b/doc/html/packet_8cpp.html
index 5d6df9e..f0b45bb 100644
--- a/doc/html/packet_8cpp.html
+++ b/doc/html/packet_8cpp.html
@@ -24,7 +24,7 @@
<table border="0" cellpadding="0" cellspacing="0">
<tr><td></td></tr>
</table>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/packet_8h-source.html b/doc/html/packet_8h-source.html
index 66310f6..f66d440 100644
--- a/doc/html/packet_8h-source.html
+++ b/doc/html/packet_8h-source.html
@@ -93,7 +93,7 @@
<a name="l00074"></a>00074 };
<a name="l00075"></a>00075
<a name="l00076"></a>00076 <span class="preprocessor">#endif</span>
-</pre></div><hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+</pre></div><hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:24 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/packet_8h.html b/doc/html/packet_8h.html
index c0103bc..94b6f21 100644
--- a/doc/html/packet_8h.html
+++ b/doc/html/packet_8h.html
@@ -29,7 +29,7 @@
<tr><td class="memItemLeft" nowrap align="right" valign="top">struct &nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="structPacket_1_1HeaderStruct.html">Packet::HeaderStruct</a></td></tr>
</table>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/satp_8py.html b/doc/html/satp_8py.html
index ca6e6cf..4a7a53d 100644
--- a/doc/html/satp_8py.html
+++ b/doc/html/satp_8py.html
@@ -28,7 +28,7 @@
<tr><td class="memItemLeft" nowrap align="right" valign="top">class &nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="classsatp_1_1SATP.html">satp::SATP</a></td></tr>
</table>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/seqWindow_8cpp.html b/doc/html/seqWindow_8cpp.html
index 00c2d9c..d220208 100644
--- a/doc/html/seqWindow_8cpp.html
+++ b/doc/html/seqWindow_8cpp.html
@@ -23,7 +23,7 @@
<table border="0" cellpadding="0" cellspacing="0">
<tr><td></td></tr>
</table>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/seqWindow_8h-source.html b/doc/html/seqWindow_8h-source.html
index 14e9c49..a58960b 100644
--- a/doc/html/seqWindow_8h-source.html
+++ b/doc/html/seqWindow_8h-source.html
@@ -81,7 +81,7 @@
<a name="l00062"></a>00062 };
<a name="l00063"></a>00063
<a name="l00064"></a>00064 <span class="preprocessor">#endif</span>
-</pre></div><hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+</pre></div><hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:24 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/seqWindow_8h.html b/doc/html/seqWindow_8h.html
index 6e76351..a52fdf5 100644
--- a/doc/html/seqWindow_8h.html
+++ b/doc/html/seqWindow_8h.html
@@ -29,7 +29,7 @@
<tr><td class="memItemLeft" nowrap align="right" valign="top">class &nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="classSeqWindow.html">SeqWindow</a></td></tr>
</table>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/signalController_8cpp.html b/doc/html/signalController_8cpp.html
index 9de66eb..462e5cc 100644
--- a/doc/html/signalController_8cpp.html
+++ b/doc/html/signalController_8cpp.html
@@ -26,7 +26,7 @@
<table border="0" cellpadding="0" cellspacing="0">
<tr><td></td></tr>
</table>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/signalController_8h-source.html b/doc/html/signalController_8h-source.html
index d819179..81148b5 100644
--- a/doc/html/signalController_8h-source.html
+++ b/doc/html/signalController_8h-source.html
@@ -138,7 +138,7 @@
<a name="l00119"></a>00119 };
<a name="l00120"></a>00120
<a name="l00121"></a>00121 <span class="preprocessor">#endif</span>
-</pre></div><hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+</pre></div><hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:24 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/signalController_8h.html b/doc/html/signalController_8h.html
index dbb49f2..48f2096 100644
--- a/doc/html/signalController_8h.html
+++ b/doc/html/signalController_8h.html
@@ -43,7 +43,7 @@
<tr><td class="memItemLeft" nowrap align="right" valign="top">class &nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="classSignalController.html">SignalController</a></td></tr>
</table>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/structPacket_1_1HeaderStruct-members.html b/doc/html/structPacket_1_1HeaderStruct-members.html
index 2908452..b20107c 100644
--- a/doc/html/structPacket_1_1HeaderStruct-members.html
+++ b/doc/html/structPacket_1_1HeaderStruct-members.html
@@ -21,7 +21,7 @@
<h1>Packet::HeaderStruct Member List</h1>This is the complete list of members for <a class="el" href="structPacket_1_1HeaderStruct.html">Packet::HeaderStruct</a>, including all inherited members.<p><table>
<tr class="memlist"><td><a class="el" href="structPacket_1_1HeaderStruct.html#c129b7cda1d848a579b689bacdabddea">sender_id</a></td><td><a class="el" href="structPacket_1_1HeaderStruct.html">Packet::HeaderStruct</a></td><td></td></tr>
<tr class="memlist"><td><a class="el" href="structPacket_1_1HeaderStruct.html#4b7b9bf68b204ca98171b7f818685521">seq_nr</a></td><td><a class="el" href="structPacket_1_1HeaderStruct.html">Packet::HeaderStruct</a></td><td></td></tr>
-</table><hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+</table><hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/structPacket_1_1HeaderStruct.html b/doc/html/structPacket_1_1HeaderStruct.html
index 474e78e..687a44a 100644
--- a/doc/html/structPacket_1_1HeaderStruct.html
+++ b/doc/html/structPacket_1_1HeaderStruct.html
@@ -61,7 +61,7 @@
</div><p>
<hr>The documentation for this struct was generated from the following file:<ul>
<li><a class="el" href="packet_8h-source.html">packet.h</a></ul>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/structParam-members.html b/doc/html/structParam-members.html
index b873070..01a4162 100644
--- a/doc/html/structParam-members.html
+++ b/doc/html/structParam-members.html
@@ -26,7 +26,7 @@
<tr class="memlist"><td><a class="el" href="structParam.html#f690604eb7652c5f5407815c5022b46c">opt</a></td><td><a class="el" href="structParam.html">Param</a></td><td></td></tr>
<tr class="memlist"><td><a class="el" href="structParam.html#dc6a71f9fa352d3ecb312e2e33354f4e">seq</a></td><td><a class="el" href="structParam.html">Param</a></td><td></td></tr>
<tr class="memlist"><td><a class="el" href="structParam.html#fa5715cd7dc0833ea8f9afcbd1db455c">src</a></td><td><a class="el" href="structParam.html">Param</a></td><td></td></tr>
-</table><hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+</table><hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/structParam.html b/doc/html/structParam.html
index 4344ad9..3bbaebc 100644
--- a/doc/html/structParam.html
+++ b/doc/html/structParam.html
@@ -144,7 +144,7 @@
</div><p>
<hr>The documentation for this struct was generated from the following file:<ul>
<li><a class="el" href="anytun_8cpp.html">anytun.cpp</a></ul>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/threadUtils_8hpp-source.html b/doc/html/threadUtils_8hpp-source.html
index 3c53a74..b6e3af9 100644
--- a/doc/html/threadUtils_8hpp-source.html
+++ b/doc/html/threadUtils_8hpp-source.html
@@ -191,7 +191,7 @@
<a name="l00172"></a>00172 };
<a name="l00173"></a>00173
<a name="l00174"></a>00174 <span class="preprocessor">#endif</span>
-</pre></div><hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+</pre></div><hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:24 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/threadUtils_8hpp.html b/doc/html/threadUtils_8hpp.html
index ec4c274..324b431 100644
--- a/doc/html/threadUtils_8hpp.html
+++ b/doc/html/threadUtils_8hpp.html
@@ -33,7 +33,7 @@
<tr><td class="memItemLeft" nowrap align="right" valign="top">class &nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="classSemaphore.html">Semaphore</a></td></tr>
</table>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/tree.html b/doc/html/tree.html
index 07f3905..461b9b4 100644
--- a/doc/html/tree.html
+++ b/doc/html/tree.html
@@ -102,6 +102,7 @@
<p><img src="ftv2vertline.png" alt="|" width=16 height=22 /><img src="ftv2node.png" alt="o" width=16 height=22 /><img src="ftv2doc.png" alt="*" width=24 height=22 /><a class="el" href="classSigUsr2Handler.html" target="basefrm">SigUsr2Handler</a></p>
<p><img src="ftv2vertline.png" alt="|" width=16 height=22 /><img src="ftv2node.png" alt="o" width=16 height=22 /><img src="ftv2doc.png" alt="*" width=24 height=22 /><a class="el" href="classSocket.html" target="basefrm">Socket</a></p>
<p><img src="ftv2vertline.png" alt="|" width=16 height=22 /><img src="ftv2node.png" alt="o" width=16 height=22 /><img src="ftv2doc.png" alt="*" width=24 height=22 /><a class="el" href="classSocketException.html" target="basefrm">SocketException</a></p>
+ <p><img src="ftv2vertline.png" alt="|" width=16 height=22 /><img src="ftv2node.png" alt="o" width=16 height=22 /><img src="ftv2doc.png" alt="*" width=24 height=22 /><a class="el" href="classSyncSocket.html" target="basefrm">SyncSocket</a></p>
<p><img src="ftv2vertline.png" alt="|" width=16 height=22 /><img src="ftv2node.png" alt="o" width=16 height=22 /><img src="ftv2doc.png" alt="*" width=24 height=22 /><a class="el" href="classTCPServerSocket.html" target="basefrm">TCPServerSocket</a></p>
<p><img src="ftv2vertline.png" alt="|" width=16 height=22 /><img src="ftv2node.png" alt="o" width=16 height=22 /><img src="ftv2doc.png" alt="*" width=24 height=22 /><a class="el" href="classTCPSocket.html" target="basefrm">TCPSocket</a></p>
<p><img src="ftv2vertline.png" alt="|" width=16 height=22 /><img src="ftv2node.png" alt="o" width=16 height=22 /><img src="ftv2doc.png" alt="*" width=24 height=22 /><a class="el" href="classTunDevice.html" target="basefrm">TunDevice</a></p>
@@ -170,6 +171,7 @@
<p><img src="ftv2vertline.png" alt="|" width=16 height=22 /><img src="ftv2vertline.png" alt="|" width=16 height=22 /><img src="ftv2lastnode.png" alt="\" width=16 height=22 /><img src="ftv2doc.png" alt="*" width=24 height=22 /><a class="el" href="classTCPServerSocket.html" target="basefrm">TCPServerSocket</a></p>
</div>
<p><img src="ftv2vertline.png" alt="|" width=16 height=22 /><img src="ftv2node.png" alt="o" width=16 height=22 /><img src="ftv2doc.png" alt="*" width=24 height=22 /><a class="el" href="classSocketException.html" target="basefrm">SocketException</a></p>
+ <p><img src="ftv2vertline.png" alt="|" width=16 height=22 /><img src="ftv2node.png" alt="o" width=16 height=22 /><img src="ftv2doc.png" alt="*" width=24 height=22 /><a class="el" href="classSyncSocket.html" target="basefrm">SyncSocket</a></p>
<p><img src="ftv2vertline.png" alt="|" width=16 height=22 /><img src="ftv2lastnode.png" alt="\" width=16 height=22 /><img src="ftv2doc.png" alt="*" width=24 height=22 /><a class="el" href="classTunDevice.html" target="basefrm">TunDevice</a></p>
</div>
<p><img src="ftv2node.png" alt="o" width=16 height=22 /><img src="ftv2doc.png" alt="*" width=24 height=22 /><a class="el" href="functions.html" target="basefrm">Class Members</a></p>
@@ -177,6 +179,7 @@
<div id="folder12">
<p><img src="ftv2vertline.png" alt="|" width=16 height=22 /><img src="ftv2node.png" alt="o" width=16 height=22 /><img src="ftv2doc.png" alt="*" width=24 height=22 /><a class="el" href="namespacesatp.html" target="basefrm">satp</a></p>
<p><img src="ftv2vertline.png" alt="|" width=16 height=22 /><img src="ftv2node.png" alt="o" width=16 height=22 /><img src="ftv2doc.png" alt="*" width=24 height=22 /><a class="el" href="namespacescapy_1_1_5.html" target="basefrm">scapy::*</a></p>
+ <p><img src="ftv2vertline.png" alt="|" width=16 height=22 /><img src="ftv2node.png" alt="o" width=16 height=22 /><img src="ftv2doc.png" alt="*" width=24 height=22 /><a class="el" href="namespacesockets.html" target="basefrm">sockets</a></p>
<p><img src="ftv2vertline.png" alt="|" width=16 height=22 /><img src="ftv2lastnode.png" alt="\" width=16 height=22 /><img src="ftv2doc.png" alt="*" width=24 height=22 /><a class="el" href="namespacestd.html" target="basefrm">std</a></p>
</div>
<p><img src="ftv2pnode.png" alt="o" width=16 height=22 onclick="toggleFolder('folder13', this)"/><img src="ftv2folderclosed.png" alt="+" width=24 height=22 onclick="toggleFolder('folder13', this)"/><a class="el" href="files.html" target="basefrm">File List</a></p>
@@ -214,6 +217,8 @@
<p><img src="ftv2vertline.png" alt="|" width=16 height=22 /><img src="ftv2node.png" alt="o" width=16 height=22 /><img src="ftv2doc.png" alt="*" width=24 height=22 /><a class="el" href="seqWindow_8h.html" target="basefrm">seqWindow.h</a></p>
<p><img src="ftv2vertline.png" alt="|" width=16 height=22 /><img src="ftv2node.png" alt="o" width=16 height=22 /><img src="ftv2doc.png" alt="*" width=24 height=22 /><a class="el" href="signalController_8cpp.html" target="basefrm">signalController.cpp</a></p>
<p><img src="ftv2vertline.png" alt="|" width=16 height=22 /><img src="ftv2node.png" alt="o" width=16 height=22 /><img src="ftv2doc.png" alt="*" width=24 height=22 /><a class="el" href="signalController_8h.html" target="basefrm">signalController.h</a></p>
+ <p><img src="ftv2vertline.png" alt="|" width=16 height=22 /><img src="ftv2node.png" alt="o" width=16 height=22 /><img src="ftv2doc.png" alt="*" width=24 height=22 /><a class="el" href="syncSocket_8cpp.html" target="basefrm">syncSocket.cpp</a></p>
+ <p><img src="ftv2vertline.png" alt="|" width=16 height=22 /><img src="ftv2node.png" alt="o" width=16 height=22 /><img src="ftv2doc.png" alt="*" width=24 height=22 /><a class="el" href="syncSocket_8h.html" target="basefrm">syncSocket.h</a></p>
<p><img src="ftv2vertline.png" alt="|" width=16 height=22 /><img src="ftv2node.png" alt="o" width=16 height=22 /><img src="ftv2doc.png" alt="*" width=24 height=22 /><a class="el" href="threadUtils_8hpp.html" target="basefrm">threadUtils.hpp</a></p>
<p><img src="ftv2vertline.png" alt="|" width=16 height=22 /><img src="ftv2node.png" alt="o" width=16 height=22 /><img src="ftv2doc.png" alt="*" width=24 height=22 /><a class="el" href="tunDevice_8cpp.html" target="basefrm">tunDevice.cpp</a></p>
<p><img src="ftv2vertline.png" alt="|" width=16 height=22 /><img src="ftv2lastnode.png" alt="\" width=16 height=22 /><img src="ftv2doc.png" alt="*" width=24 height=22 /><a class="el" href="tunDevice_8h.html" target="basefrm">tunDevice.h</a></p>
diff --git a/doc/html/tunDevice_8cpp.html b/doc/html/tunDevice_8cpp.html
index 0a8da3b..372f22f 100644
--- a/doc/html/tunDevice_8cpp.html
+++ b/doc/html/tunDevice_8cpp.html
@@ -27,7 +27,7 @@
<table border="0" cellpadding="0" cellspacing="0">
<tr><td></td></tr>
</table>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/tunDevice_8h-source.html b/doc/html/tunDevice_8h-source.html
index f9682c0..076134d 100644
--- a/doc/html/tunDevice_8h-source.html
+++ b/doc/html/tunDevice_8h-source.html
@@ -83,7 +83,7 @@
<a name="l00064"></a>00064 };
<a name="l00065"></a>00065
<a name="l00066"></a>00066 <span class="preprocessor">#endif</span>
-</pre></div><hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+</pre></div><hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:24 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/html/tunDevice_8h.html b/doc/html/tunDevice_8h.html
index a69cbbf..3065963 100644
--- a/doc/html/tunDevice_8h.html
+++ b/doc/html/tunDevice_8h.html
@@ -27,7 +27,7 @@
<tr><td class="memItemLeft" nowrap align="right" valign="top">class &nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="classTunDevice.html">TunDevice</a></td></tr>
</table>
-<hr size="1"><address style="align: right;"><small>Generated on Tue Nov 27 14:11:51 2007 for anytun by&nbsp;
+<hr size="1"><address style="align: right;"><small>Generated on Mon Dec 3 11:49:25 2007 for anytun by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
</body>
diff --git a/doc/latex/annotated.tex b/doc/latex/annotated.tex
index 433d507..bdb0d2f 100644
--- a/doc/latex/annotated.tex
+++ b/doc/latex/annotated.tex
@@ -37,6 +37,7 @@ Here are the classes, structs, unions and interfaces with brief descriptions:\be
\item\contentsline{section}{{\bf Sig\-Usr2Handler} }{\pageref{classSigUsr2Handler}}{}
\item\contentsline{section}{{\bf Socket} }{\pageref{classSocket}}{}
\item\contentsline{section}{{\bf Socket\-Exception} }{\pageref{classSocketException}}{}
+\item\contentsline{section}{{\bf Sync\-Socket} }{\pageref{classSyncSocket}}{}
\item\contentsline{section}{{\bf TCPServer\-Socket} }{\pageref{classTCPServerSocket}}{}
\item\contentsline{section}{{\bf TCPSocket} }{\pageref{classTCPSocket}}{}
\item\contentsline{section}{{\bf Tun\-Device} }{\pageref{classTunDevice}}{}
diff --git a/doc/latex/anytun_8cpp.tex b/doc/latex/anytun_8cpp.tex
index c30c570..37d6da4 100644
--- a/doc/latex/anytun_8cpp.tex
+++ b/doc/latex/anytun_8cpp.tex
@@ -31,6 +31,8 @@ struct {\bf Param}
\item
void $\ast$ {\bf sender} (void $\ast$p)
\item
+void $\ast$ {\bf sync\_\-receiver} (void $\ast$p)
+\item
void $\ast$ {\bf receiver} (void $\ast$p)
\item
int {\bf main} (int argc, char $\ast$argv[$\,$])
@@ -66,3 +68,8 @@ int {\bf main} (int argc, char $\ast$argv[$\,$])
\subsubsection{\setlength{\rightskip}{0pt plus 5cm}void$\ast$ sender (void $\ast$ {\em p})}\label{anytun_8cpp_0f2bdeb94d90f5229b9e904e592b24fd}
+\index{anytun.cpp@{anytun.cpp}!sync_receiver@{sync\_\-receiver}}
+\index{sync_receiver@{sync\_\-receiver}!anytun.cpp@{anytun.cpp}}
+\subsubsection{\setlength{\rightskip}{0pt plus 5cm}void$\ast$ sync\_\-receiver (void $\ast$ {\em p})}\label{anytun_8cpp_4fd43e7c243b1cc78c583a915dfd4d55}
+
+
diff --git a/doc/latex/doxygen.sty b/doc/latex/doxygen.sty
index d28fcf1..b8dccd9 100644
--- a/doc/latex/doxygen.sty
+++ b/doc/latex/doxygen.sty
@@ -10,8 +10,8 @@
{\fancyplain{}{\bfseries\rightmark}}
\rhead[\fancyplain{}{\bfseries\leftmark}]
{\fancyplain{}{\bfseries\thepage}}
-\rfoot[\fancyplain{}{\bfseries\scriptsize Generated on Tue Nov 27 14:11:51 2007 for anytun by Doxygen }]{}
-\lfoot[]{\fancyplain{}{\bfseries\scriptsize Generated on Tue Nov 27 14:11:51 2007 for anytun by Doxygen }}
+\rfoot[\fancyplain{}{\bfseries\scriptsize Generated on Mon Dec 3 11:49:24 2007 for anytun by Doxygen }]{}
+\lfoot[]{\fancyplain{}{\bfseries\scriptsize Generated on Mon Dec 3 11:49:24 2007 for anytun by Doxygen }}
\cfoot{}
\newenvironment{Code}
{\footnotesize}
diff --git a/doc/latex/files.tex b/doc/latex/files.tex
index 248ae98..6517797 100644
--- a/doc/latex/files.tex
+++ b/doc/latex/files.tex
@@ -33,6 +33,8 @@ Here is a list of all files with brief descriptions:\begin{CompactList}
\item\contentsline{section}{{\bf seq\-Window.h} }{\pageref{seqWindow_8h}}{}
\item\contentsline{section}{{\bf signal\-Controller.cpp} }{\pageref{signalController_8cpp}}{}
\item\contentsline{section}{{\bf signal\-Controller.h} }{\pageref{signalController_8h}}{}
+\item\contentsline{section}{{\bf sync\-Socket.cpp} }{\pageref{syncSocket_8cpp}}{}
+\item\contentsline{section}{{\bf sync\-Socket.h} }{\pageref{syncSocket_8h}}{}
\item\contentsline{section}{{\bf thread\-Utils.hpp} }{\pageref{threadUtils_8hpp}}{}
\item\contentsline{section}{{\bf tun\-Device.cpp} }{\pageref{tunDevice_8cpp}}{}
\item\contentsline{section}{{\bf tun\-Device.h} }{\pageref{tunDevice_8h}}{}
diff --git a/doc/latex/hierarchy.tex b/doc/latex/hierarchy.tex
index 92bfdcc..078b248 100644
--- a/doc/latex/hierarchy.tex
+++ b/doc/latex/hierarchy.tex
@@ -60,5 +60,6 @@ This inheritance list is sorted roughly, but not completely, alphabetically:\beg
\item \contentsline{section}{TCPServer\-Socket}{\pageref{classTCPServerSocket}}{}
\end{CompactList}
\item \contentsline{section}{Socket\-Exception}{\pageref{classSocketException}}{}
+\item \contentsline{section}{Sync\-Socket}{\pageref{classSyncSocket}}{}
\item \contentsline{section}{Tun\-Device}{\pageref{classTunDevice}}{}
\end{CompactList}
diff --git a/doc/latex/namespaces.tex b/doc/latex/namespaces.tex
index 9fbe095..8b01371 100644
--- a/doc/latex/namespaces.tex
+++ b/doc/latex/namespaces.tex
@@ -2,5 +2,6 @@
Here is a list of all namespaces with brief descriptions:\begin{CompactList}
\item\contentsline{section}{{\bf satp} }{\pageref{namespacesatp}}{}
\item\contentsline{section}{{\bf scapy::$\ast$} }{\pageref{namespacescapy_1_1_5}}{}
+\item\contentsline{section}{{\bf sockets} }{\pageref{namespacesockets}}{}
\item\contentsline{section}{{\bf std} }{\pageref{namespacestd}}{}
\end{CompactList}
diff --git a/doc/latex/refman.tex b/doc/latex/refman.tex
index 1571b49..01715b9 100644
--- a/doc/latex/refman.tex
+++ b/doc/latex/refman.tex
@@ -19,7 +19,7 @@
\vspace*{1cm}
{\large Generated by Doxygen 1.5.1}\\
\vspace*{0.5cm}
-{\small Tue Nov 27 14:11:51 2007}\\
+{\small Mon Dec 3 11:49:24 2007}\\
\end{center}
\end{titlepage}
\clearemptydoublepage
@@ -38,6 +38,7 @@
\chapter{anytun Namespace Documentation}
\input{namespacesatp}
\include{namespacescapy_1_1_5}
+\include{namespacesockets}
\include{namespacestd}
\chapter{anytun Class Documentation}
\input{classAesIcmCypher}
@@ -77,6 +78,7 @@
\include{classSigUsr2Handler}
\include{classSocket}
\include{classSocketException}
+\include{classSyncSocket}
\include{classTCPServerSocket}
\include{classTCPSocket}
\include{classTunDevice}
@@ -116,6 +118,8 @@
\include{seqWindow_8h}
\include{signalController_8cpp}
\include{signalController_8h}
+\include{syncSocket_8cpp}
+\include{syncSocket_8h}
\include{threadUtils_8hpp}
\include{tunDevice_8cpp}
\include{tunDevice_8h}
diff --git a/syncSocket.cpp b/syncSocket.cpp
new file mode 100644
index 0000000..36c02b5
--- /dev/null
+++ b/syncSocket.cpp
@@ -0,0 +1,37 @@
+
+#include "Sockets/Utility.h"
+#include "syncSocket.h"
+
+
+SyncSocket::SyncSocket(ISocketHandler& h)
+:TcpSocket(h)
+{
+ // initial connection timeout setting and number of retries
+ SetConnectTimeout(12);
+ SetConnectionRetry(5);
+
+ // Also reconnect broken link
+ SetReconnect(true);
+}
+
+
+bool SyncSocket::OnConnectRetry()
+{
+ return true;
+}
+
+
+void SyncSocket::OnReconnect()
+{
+ // ...
+ Send("Welcome back\r\n");
+}
+
+void SyncSocket::OnAccept()
+{
+ Send("Local hostname : " + Utility::GetLocalHostname() + "\n");
+ Send("Local address : " + Utility::GetLocalAddress() + "\n");
+ Send("Number of sockets in list : " + Utility::l2string(Handler().GetCount()) + "\n");
+ Send("\n");
+}
+
diff --git a/syncSocket.h b/syncSocket.h
new file mode 100644
index 0000000..75d7c7c
--- /dev/null
+++ b/syncSocket.h
@@ -0,0 +1,24 @@
+#ifndef _SYNCSOCKET_H
+#define _SYNCSOCKET_H
+
+#include "Sockets/TcpSocket.h"
+#include "Sockets/ISocketHandler.h"
+
+using namespace sockets;
+
+class SyncSocket : public TcpSocket
+{
+public:
+ SyncSocket(ISocketHandler& );
+
+ void OnAccept();
+
+ bool OnConnectRetry();
+ void OnReconnect();
+
+//private:
+// ResumeSocket2& operator=(const ResumeSocket2& ) { return *this; } // assignment operator
+};
+
+
+#endif // _SYNCSOCKET_H