diff options
author | coryan <coryan@ae88bc3d-4319-0410-8dbf-d08b4c9d3795> | 2000-06-17 00:39:09 +0000 |
---|---|---|
committer | coryan <coryan@ae88bc3d-4319-0410-8dbf-d08b4c9d3795> | 2000-06-17 00:39:09 +0000 |
commit | 9858d5181a243af42a9a15048e0bf7db4928f94c (patch) | |
tree | 8c598bbe84a843f5eb9b5fd895ba1acafa128f47 | |
parent | 6107fcba7504cca59cc0b9d85286b73507e3897e (diff) | |
download | ATCD-9858d5181a243af42a9a15048e0bf7db4928f94c.tar.gz |
ChangeLogTag:Fri Jun 16 17:30:18 2000 Carlos O'Ryan <coryan@uci.edu>
35 files changed, 3275 insertions, 159 deletions
diff --git a/ChangeLog b/ChangeLog index 34943349ae4..8ad6e97118b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,46 @@ +Fri Jun 16 17:30:18 2000 Carlos O'Ryan <coryan@uci.edu> + + * ace/RMCast/Makefile: + * ace/RMCast/RMCast.dsp: + * ace/RMCast/RMCast.dsw: + * ace/RMCast/RMCast_Export.h: + In this library we will implement a simple, small scale reliable + multicast protocol for ACE. The library is based on the ASX + classes in ACE (Task, Module and friends). + + * tests/RMCast/Makefile: + * tests/RMCast/RMCast_Tests.dsw: + The unit test directory for the RMCast library components. + + * ace/RMCast/RMCast_Fragment.h: + * ace/RMCast/RMCast_Fragment.i: + * ace/RMCast/RMCast_Fragment.cpp: + The fragmentation task. It divides a message block chain in + small fragments. The fragments are limited by the number of + bytes and the number of entries in the chain (for platforms with + limited IO vectors). + + * tests/RMCast/RMCast_Fragment_Test.cpp: + * tests/RMCast/RMCast_Fragment_Test.dsp: + Unit test for the fragmentation layer. + + * ace/RMCast/RMCast_Partial_Message.h: + * ace/RMCast/RMCast_Partial_Message.i: + * ace/RMCast/RMCast_Partial_Message.cpp: + A simply class to maintain a partial received messages, keeps + track of the missing bytes and detects when the complete message + has been received. + + * ace/RMCast/RMCast_Reassembly.h: + * ace/RMCast/RMCast_Reassembly.i: + * ace/RMCast/RMCast_Reassembly.cpp: + The reassembly layer. Uses the Partial_Message class to do a + great deal of the work. + + * tests/RMCast/RMCast_Reassembly_Test.cpp: + * tests/RMCast/RMCast_Reassembly_Test.dsp: + Unit test for the reassembly layer. + Fri Jun 16 17:00:03 2000 Carlos O'Ryan <coryan@uci.edu> * include/makeinclude/rules.bin.GNU: @@ -7,59 +50,59 @@ Fri Jun 16 17:00:03 2000 Carlos O'Ryan <coryan@uci.edu> Fri Jun 16 16:18:21 2000 Ossama Othman <ossama@uci.edu> - * ace/Makefile (DIRS): - - Descend into and build the newly added SSL directory if "make - ssl=1" is issued. - - * ace/SSL/ACE_SSL.dsp: - * ace/SSL/Makefile: - * ace/SSL/SSL_Context.cpp: - * ace/SSL/SSL_Context.h: - * ace/SSL/SSL_Export.h: - * ace/SSL/SSL_SOCK.cpp: - * ace/SSL/SSL_SOCK.h: - * ace/SSL/SSL_SOCK_Acceptor.cpp: - * ace/SSL/SSL_SOCK_Acceptor.h: - * ace/SSL/SSL_SOCK_Connector.cpp: - * ace/SSL/SSL_SOCK_Connector.h: - * ace/SSL/SSL_SOCK_Stream.cpp: - * ace/SSL/SSL_SOCK_Stream.h: - - Integrated the ACE SSL wrappers into the ACE mainline - distribution. Enable using "make ssl=1." The library that is - generated is called "libACE_SSL.so" on UNIX, and ACE_SSL{d}.dll on - Win32. - - * examples/IPC_SAP/Makefile: - - Build SSL_SAP example if "make ssl=1" is issued. - - * examples/IPC_SAP/SSL_SAP/SSL_SOCK_SAP.dsw: - * examples/IPC_SAP/SSL_SAP/Makefile: - * examples/IPC_SAP/SSL_SAP/README: - * examples/IPC_SAP/SSL_SAP/SSL-client.dsp: - * examples/IPC_SAP/SSL_SAP/SSL-server.dsp: - * examples/IPC_SAP/SSL_SAP/SSL-client-simple.cpp: - * examples/IPC_SAP/SSL_SAP/SSL-client-simple.h: - * examples/IPC_SAP/SSL_SAP/SSL-client.cpp: - * examples/IPC_SAP/SSL_SAP/SSL-client.h: - * examples/IPC_SAP/SSL_SAP/SSL-server-fancy.cpp: - * examples/IPC_SAP/SSL_SAP/SSL-server-poll.cpp: - * examples/IPC_SAP/SSL_SAP/SSL-server-simple.cpp: - * examples/IPC_SAP/SSL_SAP/SSL-server.cpp: - * examples/IPC_SAP/SSL_SAP/dummy.pem: - * examples/IPC_SAP/SSL_SAP/key.pem - * examples/IPC_SAP/SSL_SAP/local_data: - * examples/IPC_SAP/SSL_SAP/summarize: - - Integrated example that demonstratres use of the ACE SSL - wrappers. - - * include/makeinclude/wrapper_macros.GNU (ssl): - - Added make flag to enable compilation of OpenSSL support in - ACE. (e.g. make ssl=1) + * ace/Makefile (DIRS): + + Descend into and build the newly added SSL directory if "make + ssl=1" is issued. + + * ace/SSL/ACE_SSL.dsp: + * ace/SSL/Makefile: + * ace/SSL/SSL_Context.cpp: + * ace/SSL/SSL_Context.h: + * ace/SSL/SSL_Export.h: + * ace/SSL/SSL_SOCK.cpp: + * ace/SSL/SSL_SOCK.h: + * ace/SSL/SSL_SOCK_Acceptor.cpp: + * ace/SSL/SSL_SOCK_Acceptor.h: + * ace/SSL/SSL_SOCK_Connector.cpp: + * ace/SSL/SSL_SOCK_Connector.h: + * ace/SSL/SSL_SOCK_Stream.cpp: + * ace/SSL/SSL_SOCK_Stream.h: + + Integrated the ACE SSL wrappers into the ACE mainline + distribution. Enable using "make ssl=1." The library that is + generated is called "libACE_SSL.so" on UNIX, and ACE_SSL{d}.dll on + Win32. + + * examples/IPC_SAP/Makefile: + + Build SSL_SAP example if "make ssl=1" is issued. + + * examples/IPC_SAP/SSL_SAP/SSL_SOCK_SAP.dsw: + * examples/IPC_SAP/SSL_SAP/Makefile: + * examples/IPC_SAP/SSL_SAP/README: + * examples/IPC_SAP/SSL_SAP/SSL-client.dsp: + * examples/IPC_SAP/SSL_SAP/SSL-server.dsp: + * examples/IPC_SAP/SSL_SAP/SSL-client-simple.cpp: + * examples/IPC_SAP/SSL_SAP/SSL-client-simple.h: + * examples/IPC_SAP/SSL_SAP/SSL-client.cpp: + * examples/IPC_SAP/SSL_SAP/SSL-client.h: + * examples/IPC_SAP/SSL_SAP/SSL-server-fancy.cpp: + * examples/IPC_SAP/SSL_SAP/SSL-server-poll.cpp: + * examples/IPC_SAP/SSL_SAP/SSL-server-simple.cpp: + * examples/IPC_SAP/SSL_SAP/SSL-server.cpp: + * examples/IPC_SAP/SSL_SAP/dummy.pem: + * examples/IPC_SAP/SSL_SAP/key.pem + * examples/IPC_SAP/SSL_SAP/local_data: + * examples/IPC_SAP/SSL_SAP/summarize: + + Integrated example that demonstratres use of the ACE SSL + wrappers. + + * include/makeinclude/wrapper_macros.GNU (ssl): + + Added make flag to enable compilation of OpenSSL support in + ACE. (e.g. make ssl=1) Fri Jun 16 14:40:34 2000 Carlos O'Ryan <coryan@uci.edu> diff --git a/ChangeLogs/ChangeLog-02a b/ChangeLogs/ChangeLog-02a index 34943349ae4..8ad6e97118b 100644 --- a/ChangeLogs/ChangeLog-02a +++ b/ChangeLogs/ChangeLog-02a @@ -1,3 +1,46 @@ +Fri Jun 16 17:30:18 2000 Carlos O'Ryan <coryan@uci.edu> + + * ace/RMCast/Makefile: + * ace/RMCast/RMCast.dsp: + * ace/RMCast/RMCast.dsw: + * ace/RMCast/RMCast_Export.h: + In this library we will implement a simple, small scale reliable + multicast protocol for ACE. The library is based on the ASX + classes in ACE (Task, Module and friends). + + * tests/RMCast/Makefile: + * tests/RMCast/RMCast_Tests.dsw: + The unit test directory for the RMCast library components. + + * ace/RMCast/RMCast_Fragment.h: + * ace/RMCast/RMCast_Fragment.i: + * ace/RMCast/RMCast_Fragment.cpp: + The fragmentation task. It divides a message block chain in + small fragments. The fragments are limited by the number of + bytes and the number of entries in the chain (for platforms with + limited IO vectors). + + * tests/RMCast/RMCast_Fragment_Test.cpp: + * tests/RMCast/RMCast_Fragment_Test.dsp: + Unit test for the fragmentation layer. + + * ace/RMCast/RMCast_Partial_Message.h: + * ace/RMCast/RMCast_Partial_Message.i: + * ace/RMCast/RMCast_Partial_Message.cpp: + A simply class to maintain a partial received messages, keeps + track of the missing bytes and detects when the complete message + has been received. + + * ace/RMCast/RMCast_Reassembly.h: + * ace/RMCast/RMCast_Reassembly.i: + * ace/RMCast/RMCast_Reassembly.cpp: + The reassembly layer. Uses the Partial_Message class to do a + great deal of the work. + + * tests/RMCast/RMCast_Reassembly_Test.cpp: + * tests/RMCast/RMCast_Reassembly_Test.dsp: + Unit test for the reassembly layer. + Fri Jun 16 17:00:03 2000 Carlos O'Ryan <coryan@uci.edu> * include/makeinclude/rules.bin.GNU: @@ -7,59 +50,59 @@ Fri Jun 16 17:00:03 2000 Carlos O'Ryan <coryan@uci.edu> Fri Jun 16 16:18:21 2000 Ossama Othman <ossama@uci.edu> - * ace/Makefile (DIRS): - - Descend into and build the newly added SSL directory if "make - ssl=1" is issued. - - * ace/SSL/ACE_SSL.dsp: - * ace/SSL/Makefile: - * ace/SSL/SSL_Context.cpp: - * ace/SSL/SSL_Context.h: - * ace/SSL/SSL_Export.h: - * ace/SSL/SSL_SOCK.cpp: - * ace/SSL/SSL_SOCK.h: - * ace/SSL/SSL_SOCK_Acceptor.cpp: - * ace/SSL/SSL_SOCK_Acceptor.h: - * ace/SSL/SSL_SOCK_Connector.cpp: - * ace/SSL/SSL_SOCK_Connector.h: - * ace/SSL/SSL_SOCK_Stream.cpp: - * ace/SSL/SSL_SOCK_Stream.h: - - Integrated the ACE SSL wrappers into the ACE mainline - distribution. Enable using "make ssl=1." The library that is - generated is called "libACE_SSL.so" on UNIX, and ACE_SSL{d}.dll on - Win32. - - * examples/IPC_SAP/Makefile: - - Build SSL_SAP example if "make ssl=1" is issued. - - * examples/IPC_SAP/SSL_SAP/SSL_SOCK_SAP.dsw: - * examples/IPC_SAP/SSL_SAP/Makefile: - * examples/IPC_SAP/SSL_SAP/README: - * examples/IPC_SAP/SSL_SAP/SSL-client.dsp: - * examples/IPC_SAP/SSL_SAP/SSL-server.dsp: - * examples/IPC_SAP/SSL_SAP/SSL-client-simple.cpp: - * examples/IPC_SAP/SSL_SAP/SSL-client-simple.h: - * examples/IPC_SAP/SSL_SAP/SSL-client.cpp: - * examples/IPC_SAP/SSL_SAP/SSL-client.h: - * examples/IPC_SAP/SSL_SAP/SSL-server-fancy.cpp: - * examples/IPC_SAP/SSL_SAP/SSL-server-poll.cpp: - * examples/IPC_SAP/SSL_SAP/SSL-server-simple.cpp: - * examples/IPC_SAP/SSL_SAP/SSL-server.cpp: - * examples/IPC_SAP/SSL_SAP/dummy.pem: - * examples/IPC_SAP/SSL_SAP/key.pem - * examples/IPC_SAP/SSL_SAP/local_data: - * examples/IPC_SAP/SSL_SAP/summarize: - - Integrated example that demonstratres use of the ACE SSL - wrappers. - - * include/makeinclude/wrapper_macros.GNU (ssl): - - Added make flag to enable compilation of OpenSSL support in - ACE. (e.g. make ssl=1) + * ace/Makefile (DIRS): + + Descend into and build the newly added SSL directory if "make + ssl=1" is issued. + + * ace/SSL/ACE_SSL.dsp: + * ace/SSL/Makefile: + * ace/SSL/SSL_Context.cpp: + * ace/SSL/SSL_Context.h: + * ace/SSL/SSL_Export.h: + * ace/SSL/SSL_SOCK.cpp: + * ace/SSL/SSL_SOCK.h: + * ace/SSL/SSL_SOCK_Acceptor.cpp: + * ace/SSL/SSL_SOCK_Acceptor.h: + * ace/SSL/SSL_SOCK_Connector.cpp: + * ace/SSL/SSL_SOCK_Connector.h: + * ace/SSL/SSL_SOCK_Stream.cpp: + * ace/SSL/SSL_SOCK_Stream.h: + + Integrated the ACE SSL wrappers into the ACE mainline + distribution. Enable using "make ssl=1." The library that is + generated is called "libACE_SSL.so" on UNIX, and ACE_SSL{d}.dll on + Win32. + + * examples/IPC_SAP/Makefile: + + Build SSL_SAP example if "make ssl=1" is issued. + + * examples/IPC_SAP/SSL_SAP/SSL_SOCK_SAP.dsw: + * examples/IPC_SAP/SSL_SAP/Makefile: + * examples/IPC_SAP/SSL_SAP/README: + * examples/IPC_SAP/SSL_SAP/SSL-client.dsp: + * examples/IPC_SAP/SSL_SAP/SSL-server.dsp: + * examples/IPC_SAP/SSL_SAP/SSL-client-simple.cpp: + * examples/IPC_SAP/SSL_SAP/SSL-client-simple.h: + * examples/IPC_SAP/SSL_SAP/SSL-client.cpp: + * examples/IPC_SAP/SSL_SAP/SSL-client.h: + * examples/IPC_SAP/SSL_SAP/SSL-server-fancy.cpp: + * examples/IPC_SAP/SSL_SAP/SSL-server-poll.cpp: + * examples/IPC_SAP/SSL_SAP/SSL-server-simple.cpp: + * examples/IPC_SAP/SSL_SAP/SSL-server.cpp: + * examples/IPC_SAP/SSL_SAP/dummy.pem: + * examples/IPC_SAP/SSL_SAP/key.pem + * examples/IPC_SAP/SSL_SAP/local_data: + * examples/IPC_SAP/SSL_SAP/summarize: + + Integrated example that demonstratres use of the ACE SSL + wrappers. + + * include/makeinclude/wrapper_macros.GNU (ssl): + + Added make flag to enable compilation of OpenSSL support in + ACE. (e.g. make ssl=1) Fri Jun 16 14:40:34 2000 Carlos O'Ryan <coryan@uci.edu> diff --git a/ChangeLogs/ChangeLog-03a b/ChangeLogs/ChangeLog-03a index 34943349ae4..8ad6e97118b 100644 --- a/ChangeLogs/ChangeLog-03a +++ b/ChangeLogs/ChangeLog-03a @@ -1,3 +1,46 @@ +Fri Jun 16 17:30:18 2000 Carlos O'Ryan <coryan@uci.edu> + + * ace/RMCast/Makefile: + * ace/RMCast/RMCast.dsp: + * ace/RMCast/RMCast.dsw: + * ace/RMCast/RMCast_Export.h: + In this library we will implement a simple, small scale reliable + multicast protocol for ACE. The library is based on the ASX + classes in ACE (Task, Module and friends). + + * tests/RMCast/Makefile: + * tests/RMCast/RMCast_Tests.dsw: + The unit test directory for the RMCast library components. + + * ace/RMCast/RMCast_Fragment.h: + * ace/RMCast/RMCast_Fragment.i: + * ace/RMCast/RMCast_Fragment.cpp: + The fragmentation task. It divides a message block chain in + small fragments. The fragments are limited by the number of + bytes and the number of entries in the chain (for platforms with + limited IO vectors). + + * tests/RMCast/RMCast_Fragment_Test.cpp: + * tests/RMCast/RMCast_Fragment_Test.dsp: + Unit test for the fragmentation layer. + + * ace/RMCast/RMCast_Partial_Message.h: + * ace/RMCast/RMCast_Partial_Message.i: + * ace/RMCast/RMCast_Partial_Message.cpp: + A simply class to maintain a partial received messages, keeps + track of the missing bytes and detects when the complete message + has been received. + + * ace/RMCast/RMCast_Reassembly.h: + * ace/RMCast/RMCast_Reassembly.i: + * ace/RMCast/RMCast_Reassembly.cpp: + The reassembly layer. Uses the Partial_Message class to do a + great deal of the work. + + * tests/RMCast/RMCast_Reassembly_Test.cpp: + * tests/RMCast/RMCast_Reassembly_Test.dsp: + Unit test for the reassembly layer. + Fri Jun 16 17:00:03 2000 Carlos O'Ryan <coryan@uci.edu> * include/makeinclude/rules.bin.GNU: @@ -7,59 +50,59 @@ Fri Jun 16 17:00:03 2000 Carlos O'Ryan <coryan@uci.edu> Fri Jun 16 16:18:21 2000 Ossama Othman <ossama@uci.edu> - * ace/Makefile (DIRS): - - Descend into and build the newly added SSL directory if "make - ssl=1" is issued. - - * ace/SSL/ACE_SSL.dsp: - * ace/SSL/Makefile: - * ace/SSL/SSL_Context.cpp: - * ace/SSL/SSL_Context.h: - * ace/SSL/SSL_Export.h: - * ace/SSL/SSL_SOCK.cpp: - * ace/SSL/SSL_SOCK.h: - * ace/SSL/SSL_SOCK_Acceptor.cpp: - * ace/SSL/SSL_SOCK_Acceptor.h: - * ace/SSL/SSL_SOCK_Connector.cpp: - * ace/SSL/SSL_SOCK_Connector.h: - * ace/SSL/SSL_SOCK_Stream.cpp: - * ace/SSL/SSL_SOCK_Stream.h: - - Integrated the ACE SSL wrappers into the ACE mainline - distribution. Enable using "make ssl=1." The library that is - generated is called "libACE_SSL.so" on UNIX, and ACE_SSL{d}.dll on - Win32. - - * examples/IPC_SAP/Makefile: - - Build SSL_SAP example if "make ssl=1" is issued. - - * examples/IPC_SAP/SSL_SAP/SSL_SOCK_SAP.dsw: - * examples/IPC_SAP/SSL_SAP/Makefile: - * examples/IPC_SAP/SSL_SAP/README: - * examples/IPC_SAP/SSL_SAP/SSL-client.dsp: - * examples/IPC_SAP/SSL_SAP/SSL-server.dsp: - * examples/IPC_SAP/SSL_SAP/SSL-client-simple.cpp: - * examples/IPC_SAP/SSL_SAP/SSL-client-simple.h: - * examples/IPC_SAP/SSL_SAP/SSL-client.cpp: - * examples/IPC_SAP/SSL_SAP/SSL-client.h: - * examples/IPC_SAP/SSL_SAP/SSL-server-fancy.cpp: - * examples/IPC_SAP/SSL_SAP/SSL-server-poll.cpp: - * examples/IPC_SAP/SSL_SAP/SSL-server-simple.cpp: - * examples/IPC_SAP/SSL_SAP/SSL-server.cpp: - * examples/IPC_SAP/SSL_SAP/dummy.pem: - * examples/IPC_SAP/SSL_SAP/key.pem - * examples/IPC_SAP/SSL_SAP/local_data: - * examples/IPC_SAP/SSL_SAP/summarize: - - Integrated example that demonstratres use of the ACE SSL - wrappers. - - * include/makeinclude/wrapper_macros.GNU (ssl): - - Added make flag to enable compilation of OpenSSL support in - ACE. (e.g. make ssl=1) + * ace/Makefile (DIRS): + + Descend into and build the newly added SSL directory if "make + ssl=1" is issued. + + * ace/SSL/ACE_SSL.dsp: + * ace/SSL/Makefile: + * ace/SSL/SSL_Context.cpp: + * ace/SSL/SSL_Context.h: + * ace/SSL/SSL_Export.h: + * ace/SSL/SSL_SOCK.cpp: + * ace/SSL/SSL_SOCK.h: + * ace/SSL/SSL_SOCK_Acceptor.cpp: + * ace/SSL/SSL_SOCK_Acceptor.h: + * ace/SSL/SSL_SOCK_Connector.cpp: + * ace/SSL/SSL_SOCK_Connector.h: + * ace/SSL/SSL_SOCK_Stream.cpp: + * ace/SSL/SSL_SOCK_Stream.h: + + Integrated the ACE SSL wrappers into the ACE mainline + distribution. Enable using "make ssl=1." The library that is + generated is called "libACE_SSL.so" on UNIX, and ACE_SSL{d}.dll on + Win32. + + * examples/IPC_SAP/Makefile: + + Build SSL_SAP example if "make ssl=1" is issued. + + * examples/IPC_SAP/SSL_SAP/SSL_SOCK_SAP.dsw: + * examples/IPC_SAP/SSL_SAP/Makefile: + * examples/IPC_SAP/SSL_SAP/README: + * examples/IPC_SAP/SSL_SAP/SSL-client.dsp: + * examples/IPC_SAP/SSL_SAP/SSL-server.dsp: + * examples/IPC_SAP/SSL_SAP/SSL-client-simple.cpp: + * examples/IPC_SAP/SSL_SAP/SSL-client-simple.h: + * examples/IPC_SAP/SSL_SAP/SSL-client.cpp: + * examples/IPC_SAP/SSL_SAP/SSL-client.h: + * examples/IPC_SAP/SSL_SAP/SSL-server-fancy.cpp: + * examples/IPC_SAP/SSL_SAP/SSL-server-poll.cpp: + * examples/IPC_SAP/SSL_SAP/SSL-server-simple.cpp: + * examples/IPC_SAP/SSL_SAP/SSL-server.cpp: + * examples/IPC_SAP/SSL_SAP/dummy.pem: + * examples/IPC_SAP/SSL_SAP/key.pem + * examples/IPC_SAP/SSL_SAP/local_data: + * examples/IPC_SAP/SSL_SAP/summarize: + + Integrated example that demonstratres use of the ACE SSL + wrappers. + + * include/makeinclude/wrapper_macros.GNU (ssl): + + Added make flag to enable compilation of OpenSSL support in + ACE. (e.g. make ssl=1) Fri Jun 16 14:40:34 2000 Carlos O'Ryan <coryan@uci.edu> diff --git a/ace/RMCast/Makefile b/ace/RMCast/Makefile new file mode 100644 index 00000000000..87d640afe74 --- /dev/null +++ b/ace/RMCast/Makefile @@ -0,0 +1,40 @@ +#---------------------------------------------------------------------------- +# +# $Id$ +# +#---------------------------------------------------------------------------- + +MAKEFILE = Makefile +LIB = libACE_RMCast.a +SHLIB = libACE_RMCast.$(SOEXT) + +FILES= \ + RMCast_Partial_Message +TEMPLATE_FILES = \ + RMCast_Fragment \ + RMCast_Reassembly + +#---------------------------------------------------------------------------- +# Include macros and targets +#---------------------------------------------------------------------------- + +include $(ACE_ROOT)/include/makeinclude/wrapper_macros.GNU + +LSRC = $(addsuffix .cpp,$(FILES)) + +include $(ACE_ROOT)/include/makeinclude/macros.GNU +include $(ACE_ROOT)/include/makeinclude/rules.common.GNU +include $(ACE_ROOT)/include/makeinclude/rules.nonested.GNU +include $(ACE_ROOT)/include/makeinclude/rules.lib.GNU +include $(ACE_ROOT)/include/makeinclude/rules.local.GNU + +#---------------------------------------------------------------------------- +# Local targets +#---------------------------------------------------------------------------- + +#---------------------------------------------------------------------------- +# Dependencies +#---------------------------------------------------------------------------- +# DO NOT DELETE THIS LINE -- g++dep uses it. +# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. +# IF YOU PUT ANYTHING HERE IT WILL GO AWAY diff --git a/ace/RMCast/RMCast.dsp b/ace/RMCast/RMCast.dsp new file mode 100644 index 00000000000..53fdbf5cb9c --- /dev/null +++ b/ace/RMCast/RMCast.dsp @@ -0,0 +1,151 @@ +# Microsoft Developer Studio Project File - Name="RMCast" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=RMCast - 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 "RMCast.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 "RMCast.mak" CFG="RMCast - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "RMCast - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "RMCast - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "RMCast - 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 ""
+# PROP Intermediate_Dir "DLL\Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "RMCAST_EXPORTS" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\.." /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "ACE_RMCAST_BUILD_DLL" /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# 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 /nologo /dll /machine:I386
+# ADD LINK32 ace.lib /nologo /dll /machine:I386 /out:"..\..\bin\ACE_RMCast.dll" /libpath:".."
+
+!ELSEIF "$(CFG)" == "RMCast - 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 ""
+# PROP Intermediate_Dir "DLL\Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "RMCAST_EXPORTS" /YX /FD /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /I "..\.." /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "ACE_RMCAST_BUILD_DLL" /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# 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 /nologo /dll /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 aced.lib /nologo /dll /debug /machine:I386 /out:"..\..\bin\ACE_RMCastd.dll" /pdbtype:sept /libpath:".."
+
+!ENDIF
+
+# Begin Target
+
+# Name "RMCast - Win32 Release"
+# Name "RMCast - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\RMCast_Partial_Message.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=.\RMCast_Export.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\RMCast_Fragment.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\RMCast_Partial_Message.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\RMCast_Reassembly.h
+# End Source File
+# End Group
+# Begin Group "Inline Files"
+
+# PROP Default_Filter "i"
+# Begin Source File
+
+SOURCE=.\RMCast_Fragment.i
+# End Source File
+# Begin Source File
+
+SOURCE=.\RMCast_Partial_Message.i
+# End Source File
+# Begin Source File
+
+SOURCE=.\RMCast_Reassembly.i
+# End Source File
+# End Group
+# Begin Group "Template Files"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\RMCast_Fragment.cpp
+# PROP Exclude_From_Build 1
+# End Source File
+# Begin Source File
+
+SOURCE=.\RMCast_Reassembly.cpp
+# PROP Exclude_From_Build 1
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/ace/RMCast/RMCast.dsw b/ace/RMCast/RMCast.dsw new file mode 100644 index 00000000000..a322ca31785 --- /dev/null +++ b/ace/RMCast/RMCast.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "RMCast"=.\RMCast.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/ace/RMCast/RMCast_Export.h b/ace/RMCast/RMCast_Export.h new file mode 100644 index 00000000000..665d4ecf229 --- /dev/null +++ b/ace/RMCast/RMCast_Export.h @@ -0,0 +1,40 @@ +// -*- C++ -*- +// $Id$ +// Definition for Win32 Export directives. +// This file is generated automatically by +// generate_export_file.pl +// ------------------------------ +#if !defined (ACE_RMCAST_EXPORT_H) +#define ACE_RMCAST_EXPORT_H + +#include "ace/config-all.h" + +#if !defined (ACE_RMCAST_HAS_DLL) +#define ACE_RMCAST_HAS_DLL 1 +#endif /* ! ACE_RMCAST_HAS_DLL */ + +#if defined (ACE_RMCAST_HAS_DLL) +# if (ACE_RMCAST_HAS_DLL == 1) +# if defined (ACE_RMCAST_BUILD_DLL) +# define ACE_RMCast_Export ACE_Proper_Export_Flag +# define ACE_RMCAST_SINGLETON_DECLARATION(T) ACE_EXPORT_SINGLETON_DECLARATION (T) +# define ACE_RMCAST_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) ACE_EXPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) +# else +# define ACE_RMCast_Export ACE_Proper_Import_Flag +# define ACE_RMCAST_SINGLETON_DECLARATION(T) ACE_IMPORT_SINGLETON_DECLARATION (T) +# define ACE_RMCAST_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) ACE_IMPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) +# endif /* ACE_RMCAST_BUILD_DLL */ +# else +# define ACE_RMCast_Export +# define ACE_RMCAST_SINGLETON_DECLARATION(T) +# define ACE_RMCAST_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) +# endif /* ! ACE_RMCAST_HAS_DLL == 1 */ +#else +# define ACE_RMCast_Export +# define ACE_RMCAST_SINGLETON_DECLARATION(T) +# define ACE_RMCAST_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) +#endif /* ACE_RMCAST_HAS_DLL */ + +#endif /* ACE_RMCAST_EXPORT_H */ + +// End of auto generated file. diff --git a/ace/RMCast/RMCast_Fragment.cpp b/ace/RMCast/RMCast_Fragment.cpp new file mode 100644 index 00000000000..0578690f018 --- /dev/null +++ b/ace/RMCast/RMCast_Fragment.cpp @@ -0,0 +1,204 @@ +// $Id$ + +#ifndef ACE_RMCAST_FRAGMENT_C +#define ACE_RMCAST_FRAGMENT_C + +#include "RMCast_Fragment.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#if !defined (__ACE_INLINE__) +#include "RMCast_Fragment.i" +#endif /* __ACE_INLINE__ */ + +ACE_RCSID(ace, RMCast_Fragment, "$Id$") + + +template <ACE_SYNCH_DECL> +ACE_RMCast_Fragment<ACE_SYNCH_USE>:: +ACE_RMCast_Fragment (ACE_Thread_Manager *thr_mgr, + ACE_Message_Queue<ACE_SYNCH_USE> *mq) + : ACE_Task<ACE_SYNCH_USE> (thr_mgr, mq) + , max_fragment_size_ (ACE_RMCAST_DEFAULT_FRAGMENT_SIZE) +{ +} + +template <ACE_SYNCH_DECL> +ACE_RMCast_Fragment<ACE_SYNCH_USE>:: +~ACE_RMCast_Fragment (void) +{ +} + +template <ACE_SYNCH_DECL> int +ACE_RMCast_Fragment<ACE_SYNCH_USE>::put (ACE_Message_Block *mb, + ACE_Time_Value *tv) +{ + // @@ We should keep the total size precomputed + size_t total_size = mb->total_size (); + +#if defined (ACE_HAS_BROKEN_DGRAM_SENDV) + const int TAO_WRITEV_MAX = IOV_MAX - 1; +#else + const int TAO_WRITEV_MAX = IOV_MAX; +#endif /* ACE_HAS_BROKEN_DGRAM_SENDV */ + + const size_t max_fragment_payload = this->max_fragment_size_; + + // Iterate over all the message blocks in the chain. If there is + // enough data to send an MTU then it is sent immediately. + // The last fragment is sent with whatever data remains. + // A single fragment can expand multiple message blocks, put + // together in an <iovec> array, it is also possible that a single + // message block requires multiple fragments... so the code below is + // as simple as possible, but not any simpler ;-) + + + // The first piece of each fragment is a header that contains: + // - A sequence number for reassembly, this is unrelated to + // the sequence number for re-transmission. + // NOTE: yes, this increases the bandwidth requires by 4 bytes on + // each message, I don't think this is a big deal. + // - A fragment offset for reassembly. + // - The total size of the message, so the reassembly layer knows + // when a complete message has been received. + + ACE_UINT32 message_sequence_number; + ACE_UINT32 fragment_offset = 0; + { + ACE_GUARD_RETURN (ACE_SYNCH_MUTEX_T, ace_mon, this->mutex_, -1); + message_sequence_number = ++(this->sequence_number_generator_); + } + + + // The underlying transport layer can only tolerate so many elements + // in a chain, so we must count them and send a fragment if we are + // going over the limit. + + ACE_Message_Block blocks[TAO_WRITEV_MAX]; + + // The first message block contains the fragmentation layer + // header... + ACE_UINT32 header[3]; + header[0] = ACE_HTONL(message_sequence_number); + header[1] = ACE_HTONL(fragment_offset); + header[2] = ACE_HTONL(total_size); + + const size_t fragment_header_size = sizeof(header); + + blocks[0].init (ACE_reinterpret_cast(char*,header), + fragment_header_size); + blocks[0].wr_ptr (fragment_header_size); + + // How many elements of the <blocks> array are in use... + int iovcnt = 1; + + // The size of the current message, adding the size of all its + // message blocks. + size_t fragment_size = fragment_header_size; + + for (ACE_Message_Block* b = mb; b != 0; b = b->cont ()) + { + // Add the block to the vector... + + ACE_Message_Block *last_block = blocks + iovcnt; + + last_block->data_block (b->data_block ()->duplicate ()); + last_block->rd_ptr (b->rd_ptr ()); + last_block->wr_ptr (b->wr_ptr ()); + last_block->cont (0); + // Set the continuation field + blocks[iovcnt - 1].cont (last_block); + + size_t last_block_length = last_block->length (); + + // Recompute the state of the fragment + fragment_size += last_block_length; + iovcnt++; + + while (fragment_size >= max_fragment_payload) + { + // We have filled a fragment. It is possible that we need + // to split the last message block in multiple fragments, + // thus the loop above... + + // First adjust the last message block to exactly fit in the + // fragment: + size_t last_sent_mb_len = + max_fragment_payload - (fragment_size - last_block_length); + + // Send only enough data of the last message block to fill + // the fragment... + last_block->wr_ptr (last_block->rd_ptr () + + last_sent_mb_len); + + if (this->put_next (blocks, tv) == -1) + return -1; + + // adjust the offset + fragment_offset += max_fragment_payload - fragment_header_size; + header[1] = ACE_HTONL(fragment_offset); + + // Now compute how much data is left in the last message + // block, to check if we should continue sending it... + last_block_length -= last_sent_mb_len; + if (last_block_length == 0) + { + // No more data from this message block, just continue + // the outer loop... + iovcnt = 1; + fragment_size = fragment_header_size; + blocks[0].cont (0); + break; // while + } + + // There is some data left, we try to send it in a single + // fragment, if it is still too big the beginning of this + // loop will adjust things. + + // We must put the data in the right place in the array.. + char *rd_ptr = last_block->rd_ptr () + last_sent_mb_len; + char *wr_ptr = rd_ptr + last_block_length; + blocks[1].data_block (last_block->replace_data_block (0)); + + // And determine what segment of the data will be sent.. + blocks[1].rd_ptr (rd_ptr); + blocks[1].wr_ptr (wr_ptr); + blocks[1].cont (0); + last_block = &blocks[1]; + + // Setup the cont field... + blocks[0].cont (last_block); + + // Adjust the state of the fragment + fragment_size = last_block_length + fragment_header_size; + iovcnt = 2; + + // Notice that if <fragment_size> is too big the start of + // this loop will continue the fragmentation. + } + + // It is also possible to fill up the iovec array before the + // fragment is completed, in this case we must send whatever we + // have: + if (iovcnt == TAO_WRITEV_MAX) + { + if (this->put_next (blocks, tv) == -1) + return -1; + + fragment_offset += fragment_size - fragment_header_size; + header[1] = ACE_HTONL(fragment_offset); + iovcnt = 1; + fragment_size = fragment_header_size; + blocks[0].cont (0); + } + } + + if (iovcnt == 1) + return 0; + + return this->put_next (blocks, tv); +} + +#endif /* ACE_RMCAST_FRAGMENT_C */ diff --git a/ace/RMCast/RMCast_Fragment.h b/ace/RMCast/RMCast_Fragment.h new file mode 100644 index 00000000000..8aa7024770e --- /dev/null +++ b/ace/RMCast/RMCast_Fragment.h @@ -0,0 +1,68 @@ +// $Id$ + +// ============================================================================ +// +// = DESCRIPTION +// The fragmentation task for the reliable multicast library +// +// = AUTHOR +// Carlos O'Ryan <coryan@cs.wustl.edu> +// +// ============================================================================ + +#ifndef ACE_RMCAST_FRAGMENT_H +#define ACE_RMCAST_FRAGMENT_H +#include "ace/pre.h" + +#include "RMCast_Export.h" +#include "ace/Task.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#ifndef ACE_RMCAST_DEFAULT_FRAGMENT_SIZE +# define ACE_RMCAST_DEFAULT_FRAGMENT_SIZE 1024 +#endif /* ACE_RMCAST_DEFAULT_FRAGMENT_SIZE */ + +template <ACE_SYNCH_DECL> +class ACE_RMCast_Export ACE_RMCast_Fragment : public ACE_Task<ACE_SYNCH_USE> +{ +public: + ACE_RMCast_Fragment (ACE_Thread_Manager *thr_mgr = 0, + ACE_Message_Queue<ACE_SYNCH_USE> *mq = 0); + // Constructor + + virtual ~ACE_RMCast_Fragment (void); + // Destructor + + size_t max_fragment_size (void) const; + // Accessor for the max_fragment size. + // There is no modifier, the maximum fragment size is obtained using + // feedback from the lower layer (transport?) + + // = The ACE_Task methods + int put (ACE_Message_Block *, ACE_Time_Value *timeout = 0); + +private: + size_t max_fragment_size_; + + ACE_SYNCH_MUTEX_T mutex_; + ACE_UINT32 sequence_number_generator_; + // The sequence number generator +}; + +#if defined (__ACE_INLINE__) +#include "RMCast_Fragment.i" +#endif /* __ACE_INLINE__ */ + +#if defined (ACE_TEMPLATES_REQUIRE_SOURCE) +#include "RMCast_Fragment.cpp" +#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */ + +#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA) +#pragma implementation ("RMCast_Fragment.cpp") +#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */ + +#include "ace/post.h" +#endif /* ACE_RMCAST_FRAGMENT_H */ diff --git a/ace/RMCast/RMCast_Fragment.i b/ace/RMCast/RMCast_Fragment.i new file mode 100644 index 00000000000..0cf9f7eea9b --- /dev/null +++ b/ace/RMCast/RMCast_Fragment.i @@ -0,0 +1,8 @@ +// $Id$ + +template <ACE_SYNCH_DECL> ACE_INLINE size_t +ACE_RMCast_Fragment<ACE_SYNCH_USE>::max_fragment_size (void) const +{ + return this->max_fragment_size_; +} + diff --git a/ace/RMCast/RMCast_Partial_Message.cpp b/ace/RMCast/RMCast_Partial_Message.cpp new file mode 100644 index 00000000000..054619d6998 --- /dev/null +++ b/ace/RMCast/RMCast_Partial_Message.cpp @@ -0,0 +1,180 @@ +// $Id$ + +#include "RMCast_Partial_Message.h" + +#if !defined (__ACE_INLINE__) +#include "RMCast_Partial_Message.i" +#endif /* __ACE_INLINE__ */ + +ACE_RCSID(ace, RMCast_Partial_Message, "$Id$") + +ACE_RMCast_Partial_Message:: +ACE_RMCast_Partial_Message (ACE_UINT32 message_size) + : max_hole_count_ (ACE_RMCAST_DEFAULT_HOLE_COUNT), + hole_count_ (1) +{ + ACE_NEW (this->hole_list_, + ACE_RMCast_Partial_Message::Hole[this->max_hole_count_]); + this->hole_list_[0].start = 0; + this->hole_list_[0].end = message_size; + + this->message_body_.size (message_size); + this->message_body_.wr_ptr (message_size); +} + +ACE_RMCast_Partial_Message:: +~ACE_RMCast_Partial_Message (void) +{ + delete[] this->hole_list_; +} + +int +ACE_RMCast_Partial_Message::fragment_received (ACE_UINT32 message_size, + ACE_UINT32 offset, + ACE_Message_Block *mb) +{ + // Just copy the data... + char *rd_ptr = this->message_body_.rd_ptr () + offset; + size_t total_length = mb->length () - 12; + if (total_length > 0) + { + ACE_OS::memcpy (rd_ptr, + mb->rd_ptr () + 12, + total_length); + rd_ptr += total_length; + } + { + for (const ACE_Message_Block *i = mb->cont (); i != 0; i = i->cont ()) + { + ACE_OS::memcpy (rd_ptr, i->rd_ptr (), i->length ()); + rd_ptr += i->length (); + total_length += i->length (); + } + } + + // The algorithm works like this: + // + // For each hole we determine if there is an intersection between + // the hole and the incoming fragment. If there is none we do + // nothing (actually since the holes are ordered we can stop the + // iteration if the + + ACE_UINT32 start = offset; + ACE_UINT32 end = offset + total_length; + + for (size_t i = 0; i < this->hole_count_; ++i) + { + Hole& hole = this->hole_list_[i]; + + if (end <= hole.start) + return 0; + if (start >= hole.end) + continue; + + // OK there is some intersection. + + // There are only three cases for the <start> value: + // start < hole.start + // start == hole.start + // hole.start < start < hole.end + // + // But the code for both start == hole.start and start < + // hole.start is identical.... + + if (start <= hole.start) + { + if (end < hole.end) + { + // In this case we shrink the hole + hole.start = end; + return 0; + } + else // end >= hole.end + { + // We remove the hole, and continue the iteration... + if (this->remove_hole (i) == -1) + return -1; + continue; + } + } + else // hole.start < start < hole.end + { + if (end >= hole.end) + { + // Just adjust the size of the hole... + hole.start = start; + return 0; + } + else // if (end < hole.end) + { + // Nasty, we need to insert a new hole... + if (this->insert_hole (i, end, hole.end) == -1) + return -1; + // and change the old hole... + // NOTE: we have to refetch it because the array may + // have been reallocated! + this->hole_list_[i].end = start; + continue; + } + } + } + return 0; + // @@ OLD COMMENTS, the algorithm has changed since! + // There are several cases: + // + // 1) The fragment is completely contained in data already received, + // nothing changes in this case. + // + // 2) Part of the fragment is contained in data already received and + // part is new data: + // 2.1) The new data closes a hole, remove it from the list + // 2.2) The beginning of the new fragment is the new data, reduce + // the size of the hole + // 2.3) The end of the new fragment is the new data, increment + // the size of the received block + // + // 3) The fragment is completely contained in a hole + // 3.1) It closes the hole, remove it from the list + // 3.2) It starts at the beginning of a hole, grow the received + // block + // 3.3) It ends at the end of a hole, reduce the hole size + // 3.4) It is in the middle of a hole, insert a new hole + // +} + +int +ACE_RMCast_Partial_Message::insert_hole (size_t i, + ACE_UINT32 start, + ACE_UINT32 end) +{ + if (this->hole_count_ == this->max_hole_count_) + { + this->max_hole_count_ *= 2; + Hole *tmp; + ACE_NEW_RETURN (tmp, Hole[this->max_hole_count_], -1); + for (size_t j = 0; j != this->hole_count_; ++j) + { + tmp[j] = this->hole_list_[j]; + } + } + for (size_t j = this->hole_count_; j != i + 1; --j) + { + this->hole_list_[j] = this->hole_list_[j - 1]; + } + + this->hole_list_[i + 1].start = start; + this->hole_list_[i + 1].end = end; + this->hole_count_++; + + return 0; +} + +int +ACE_RMCast_Partial_Message::remove_hole (size_t i) +{ + for (size_t j = i; j != this->hole_count_ - 1; ++j) + this->hole_list_[j] = this->hole_list_[j + 1]; + + this->hole_count_--; + return 0; +} diff --git a/ace/RMCast/RMCast_Partial_Message.h b/ace/RMCast/RMCast_Partial_Message.h new file mode 100644 index 00000000000..af66435825a --- /dev/null +++ b/ace/RMCast/RMCast_Partial_Message.h @@ -0,0 +1,74 @@ +// $Id$ + +// ============================================================================ +// +// = DESCRIPTION +// Helper class used in the reassembly layer of the realiable +// multicast library. +// +// = AUTHOR +// Carlos O'Ryan <coryan@cs.wustl.edu> +// +// ============================================================================ + +#ifndef ACE_RMCAST_PARTIAL_MESSAGE_H +#define ACE_RMCAST_PARTIAL_MESSAGE_H +#include "ace/pre.h" + +#include "RMCast_Export.h" +#include "ace/Task.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#ifndef ACE_RMCAST_DEFAULT_HOLE_COUNT +#define ACE_RMCAST_DEFAULT_HOLE_COUNT 16 +#endif /* ACE_RMCAST_DEFAULT_HOLE_COUNT */ + +class ACE_RMCast_Export ACE_RMCast_Partial_Message +{ +public: + ACE_RMCast_Partial_Message (ACE_UINT32 message_size); + ~ACE_RMCast_Partial_Message (void); + + int fragment_received (ACE_UINT32 message_size, + ACE_UINT32 offset, + ACE_Message_Block *mb); + int is_complete (void) const; + + ACE_Message_Block *message_body (void); + // Return the body of the message, the memory is owned by the + // class. + +private: + int insert_hole (size_t i, + ACE_UINT32 start, + ACE_UINT32 end); + // Insert a new hole into the list + + int remove_hole (size_t i); + // Remove a hole from the list + +private: + ACE_Message_Block message_body_; + // Used to rebuild the body of the message + + struct Hole + { + ACE_UINT32 start; + ACE_UINT32 end; + }; + + Hole *hole_list_; + size_t max_hole_count_; + size_t hole_count_; + // The current list of holes in the message_body. +}; + +#if defined (__ACE_INLINE__) +#include "RMCast_Partial_Message.i" +#endif /* __ACE_INLINE__ */ + +#include "ace/post.h" +#endif /* ACE_RMCAST_PARTIAL_MESSAGE_H */ diff --git a/ace/RMCast/RMCast_Partial_Message.i b/ace/RMCast/RMCast_Partial_Message.i new file mode 100644 index 00000000000..7be89aa1932 --- /dev/null +++ b/ace/RMCast/RMCast_Partial_Message.i @@ -0,0 +1,15 @@ +// $Id$ + +ACE_INLINE int +ACE_RMCast_Partial_Message::is_complete (void) const +{ + return (this->hole_count_ == 0) + || (this->hole_count_ == 1 + && this->hole_list_[0].start == this->hole_list_[0].end); +} + +ACE_INLINE ACE_Message_Block * +ACE_RMCast_Partial_Message::message_body (void) +{ + return &this->message_body_; +} diff --git a/ace/RMCast/RMCast_Reassembly.cpp b/ace/RMCast/RMCast_Reassembly.cpp new file mode 100644 index 00000000000..be56e6cd9e8 --- /dev/null +++ b/ace/RMCast/RMCast_Reassembly.cpp @@ -0,0 +1,108 @@ +// $Id$ + +#ifndef ACE_RMCAST_REASSEMBLY_C +#define ACE_RMCAST_REASSEMBLY_C + +#include "RMCast_Reassembly.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#include "RMCast_Partial_Message.h" + +#if !defined (__ACE_INLINE__) +#include "RMCast_Reassembly.i" +#endif /* __ACE_INLINE__ */ + +ACE_RCSID(ace, RMCast_Reassembly, "$Id$") + + +template <ACE_SYNCH_DECL> +ACE_RMCast_Reassembly<ACE_SYNCH_USE>:: +ACE_RMCast_Reassembly (ACE_Thread_Manager *thr_mgr, + ACE_Message_Queue<ACE_SYNCH_USE> *mq) + : ACE_Task<ACE_SYNCH_USE> (thr_mgr, mq) +{ +} + +template <ACE_SYNCH_DECL> +ACE_RMCast_Reassembly<ACE_SYNCH_USE>:: +~ACE_RMCast_Reassembly (void) +{ + for (Message_Map_Iterator i = this->messages_.begin (); + i != this->messages_.end (); + ++i) + { + ACE_RMCast_Partial_Message *message = (*i).int_id_; + if (message != 0) + delete message; + } + this->messages_.unbind_all (); +} + +template <ACE_SYNCH_DECL> int +ACE_RMCast_Reassembly<ACE_SYNCH_USE>::put (ACE_Message_Block *mb, + ACE_Time_Value *tv) +{ + ACE_UINT32 header[3]; + size_t fragment_header_size = sizeof(header); + + if (mb->length () < fragment_header_size) + ACE_ERROR_RETURN ((LM_ERROR, + "Message block too small, " + "not enough room for the header\n"), + -1); + + ACE_OS::memcpy (header, mb->rd_ptr (), fragment_header_size); + + ACE_UINT32 message_sequence_number = ACE_NTOHL(header[0]); + ACE_UINT32 offset = ACE_NTOHL(header[1]); + ACE_UINT32 message_size = ACE_NTOHL(header[2]); + + if (mb->length () + offset > message_size) + return -1; // Corrupt message? + + ACE_RMCast_Partial_Message *message; + + { + ACE_GUARD_RETURN (ACE_SYNCH_MUTEX_T, ace_mon, this->mutex_, -1); + if (this->messages_.find (message_sequence_number, message) == -1) + { + ACE_NEW_RETURN (message, + ACE_RMCast_Partial_Message (message_size), + -1); + + if (this->messages_.bind (message_sequence_number, + message) == -1) + return -1; // Internal error? + } + + // The message was in the collection, but it has been received + // already, this is a duplicate fragment, just drop it. + if (message == 0) + return 0; + + if (message->fragment_received (message_size, + offset, + mb) == -1) + return -1; + + if (!message->is_complete ()) + return 0; + + // Remove the message from the collection, but leave a marker + // to indicate that it was already received... + if (this->messages_.rebind (message_sequence_number, 0) == -1) + return -1; + } + + // Push the message... + int r = this->put_next (message->message_body (), tv); + + delete message; + + return r; +} + +#endif /* ACE_RMCAST_REASSEMBLY_C */ diff --git a/ace/RMCast/RMCast_Reassembly.h b/ace/RMCast/RMCast_Reassembly.h new file mode 100644 index 00000000000..456c060948a --- /dev/null +++ b/ace/RMCast/RMCast_Reassembly.h @@ -0,0 +1,67 @@ +// $Id$ + +// ============================================================================ +// +// = DESCRIPTION +// The reassembly task for the reliable multicast library +// +// = AUTHOR +// Carlos O'Ryan <coryan@cs.wustl.edu> +// +// ============================================================================ + +#ifndef ACE_RMCAST_REASSEMBLY_H +#define ACE_RMCAST_REASSEMBLY_H +#include "ace/pre.h" + +#include "RMCast_Export.h" +#include "ace/Task.h" +#include "ace/Hash_Map_Manager.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +class ACE_RMCast_Partial_Message; + +template <ACE_SYNCH_DECL> +class ACE_RMCast_Export ACE_RMCast_Reassembly : public ACE_Task<ACE_SYNCH_USE> +{ +public: + ACE_RMCast_Reassembly (ACE_Thread_Manager *thr_mgr = 0, + ACE_Message_Queue<ACE_SYNCH_USE> *mq = 0); + // Constructor + + virtual ~ACE_RMCast_Reassembly (void); + // Destructor + + // = The ACE_Task methods + int put (ACE_Message_Block *, ACE_Time_Value *timeout = 0); + +private: + ACE_SYNCH_MUTEX_T mutex_; + typedef + ACE_Hash_Map_Manager<ACE_UINT32,ACE_RMCast_Partial_Message*,ACE_Null_Mutex> + Message_Map; + typedef + ACE_Hash_Map_Iterator<ACE_UINT32,ACE_RMCast_Partial_Message*,ACE_Null_Mutex> + Message_Map_Iterator; + + Message_Map messages_; + // The array of partially received messages +}; + +#if defined (__ACE_INLINE__) +#include "RMCast_Reassembly.i" +#endif /* __ACE_INLINE__ */ + +#if defined (ACE_TEMPLATES_REQUIRE_SOURCE) +#include "RMCast_Reassembly.cpp" +#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */ + +#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA) +#pragma implementation ("RMCast_Reassembly.cpp") +#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */ + +#include "ace/post.h" +#endif /* ACE_RMCAST_REASSEMBLY_H */ diff --git a/ace/RMCast/RMCast_Reassembly.i b/ace/RMCast/RMCast_Reassembly.i new file mode 100644 index 00000000000..74e88caa0c5 --- /dev/null +++ b/ace/RMCast/RMCast_Reassembly.i @@ -0,0 +1,2 @@ +// $Id$ + diff --git a/protocols/ace/RMCast/Makefile b/protocols/ace/RMCast/Makefile new file mode 100644 index 00000000000..87d640afe74 --- /dev/null +++ b/protocols/ace/RMCast/Makefile @@ -0,0 +1,40 @@ +#---------------------------------------------------------------------------- +# +# $Id$ +# +#---------------------------------------------------------------------------- + +MAKEFILE = Makefile +LIB = libACE_RMCast.a +SHLIB = libACE_RMCast.$(SOEXT) + +FILES= \ + RMCast_Partial_Message +TEMPLATE_FILES = \ + RMCast_Fragment \ + RMCast_Reassembly + +#---------------------------------------------------------------------------- +# Include macros and targets +#---------------------------------------------------------------------------- + +include $(ACE_ROOT)/include/makeinclude/wrapper_macros.GNU + +LSRC = $(addsuffix .cpp,$(FILES)) + +include $(ACE_ROOT)/include/makeinclude/macros.GNU +include $(ACE_ROOT)/include/makeinclude/rules.common.GNU +include $(ACE_ROOT)/include/makeinclude/rules.nonested.GNU +include $(ACE_ROOT)/include/makeinclude/rules.lib.GNU +include $(ACE_ROOT)/include/makeinclude/rules.local.GNU + +#---------------------------------------------------------------------------- +# Local targets +#---------------------------------------------------------------------------- + +#---------------------------------------------------------------------------- +# Dependencies +#---------------------------------------------------------------------------- +# DO NOT DELETE THIS LINE -- g++dep uses it. +# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. +# IF YOU PUT ANYTHING HERE IT WILL GO AWAY diff --git a/protocols/ace/RMCast/RMCast.dsp b/protocols/ace/RMCast/RMCast.dsp new file mode 100644 index 00000000000..53fdbf5cb9c --- /dev/null +++ b/protocols/ace/RMCast/RMCast.dsp @@ -0,0 +1,151 @@ +# Microsoft Developer Studio Project File - Name="RMCast" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=RMCast - 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 "RMCast.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 "RMCast.mak" CFG="RMCast - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "RMCast - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "RMCast - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "RMCast - 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 ""
+# PROP Intermediate_Dir "DLL\Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "RMCAST_EXPORTS" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\.." /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "ACE_RMCAST_BUILD_DLL" /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# 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 /nologo /dll /machine:I386
+# ADD LINK32 ace.lib /nologo /dll /machine:I386 /out:"..\..\bin\ACE_RMCast.dll" /libpath:".."
+
+!ELSEIF "$(CFG)" == "RMCast - 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 ""
+# PROP Intermediate_Dir "DLL\Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "RMCAST_EXPORTS" /YX /FD /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /I "..\.." /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "ACE_RMCAST_BUILD_DLL" /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# 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 /nologo /dll /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 aced.lib /nologo /dll /debug /machine:I386 /out:"..\..\bin\ACE_RMCastd.dll" /pdbtype:sept /libpath:".."
+
+!ENDIF
+
+# Begin Target
+
+# Name "RMCast - Win32 Release"
+# Name "RMCast - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\RMCast_Partial_Message.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=.\RMCast_Export.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\RMCast_Fragment.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\RMCast_Partial_Message.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\RMCast_Reassembly.h
+# End Source File
+# End Group
+# Begin Group "Inline Files"
+
+# PROP Default_Filter "i"
+# Begin Source File
+
+SOURCE=.\RMCast_Fragment.i
+# End Source File
+# Begin Source File
+
+SOURCE=.\RMCast_Partial_Message.i
+# End Source File
+# Begin Source File
+
+SOURCE=.\RMCast_Reassembly.i
+# End Source File
+# End Group
+# Begin Group "Template Files"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\RMCast_Fragment.cpp
+# PROP Exclude_From_Build 1
+# End Source File
+# Begin Source File
+
+SOURCE=.\RMCast_Reassembly.cpp
+# PROP Exclude_From_Build 1
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/protocols/ace/RMCast/RMCast.dsw b/protocols/ace/RMCast/RMCast.dsw new file mode 100644 index 00000000000..a322ca31785 --- /dev/null +++ b/protocols/ace/RMCast/RMCast.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "RMCast"=.\RMCast.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/protocols/ace/RMCast/RMCast_Export.h b/protocols/ace/RMCast/RMCast_Export.h new file mode 100644 index 00000000000..665d4ecf229 --- /dev/null +++ b/protocols/ace/RMCast/RMCast_Export.h @@ -0,0 +1,40 @@ +// -*- C++ -*- +// $Id$ +// Definition for Win32 Export directives. +// This file is generated automatically by +// generate_export_file.pl +// ------------------------------ +#if !defined (ACE_RMCAST_EXPORT_H) +#define ACE_RMCAST_EXPORT_H + +#include "ace/config-all.h" + +#if !defined (ACE_RMCAST_HAS_DLL) +#define ACE_RMCAST_HAS_DLL 1 +#endif /* ! ACE_RMCAST_HAS_DLL */ + +#if defined (ACE_RMCAST_HAS_DLL) +# if (ACE_RMCAST_HAS_DLL == 1) +# if defined (ACE_RMCAST_BUILD_DLL) +# define ACE_RMCast_Export ACE_Proper_Export_Flag +# define ACE_RMCAST_SINGLETON_DECLARATION(T) ACE_EXPORT_SINGLETON_DECLARATION (T) +# define ACE_RMCAST_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) ACE_EXPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) +# else +# define ACE_RMCast_Export ACE_Proper_Import_Flag +# define ACE_RMCAST_SINGLETON_DECLARATION(T) ACE_IMPORT_SINGLETON_DECLARATION (T) +# define ACE_RMCAST_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) ACE_IMPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) +# endif /* ACE_RMCAST_BUILD_DLL */ +# else +# define ACE_RMCast_Export +# define ACE_RMCAST_SINGLETON_DECLARATION(T) +# define ACE_RMCAST_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) +# endif /* ! ACE_RMCAST_HAS_DLL == 1 */ +#else +# define ACE_RMCast_Export +# define ACE_RMCAST_SINGLETON_DECLARATION(T) +# define ACE_RMCAST_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) +#endif /* ACE_RMCAST_HAS_DLL */ + +#endif /* ACE_RMCAST_EXPORT_H */ + +// End of auto generated file. diff --git a/protocols/ace/RMCast/RMCast_Fragment.cpp b/protocols/ace/RMCast/RMCast_Fragment.cpp new file mode 100644 index 00000000000..0578690f018 --- /dev/null +++ b/protocols/ace/RMCast/RMCast_Fragment.cpp @@ -0,0 +1,204 @@ +// $Id$ + +#ifndef ACE_RMCAST_FRAGMENT_C +#define ACE_RMCAST_FRAGMENT_C + +#include "RMCast_Fragment.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#if !defined (__ACE_INLINE__) +#include "RMCast_Fragment.i" +#endif /* __ACE_INLINE__ */ + +ACE_RCSID(ace, RMCast_Fragment, "$Id$") + + +template <ACE_SYNCH_DECL> +ACE_RMCast_Fragment<ACE_SYNCH_USE>:: +ACE_RMCast_Fragment (ACE_Thread_Manager *thr_mgr, + ACE_Message_Queue<ACE_SYNCH_USE> *mq) + : ACE_Task<ACE_SYNCH_USE> (thr_mgr, mq) + , max_fragment_size_ (ACE_RMCAST_DEFAULT_FRAGMENT_SIZE) +{ +} + +template <ACE_SYNCH_DECL> +ACE_RMCast_Fragment<ACE_SYNCH_USE>:: +~ACE_RMCast_Fragment (void) +{ +} + +template <ACE_SYNCH_DECL> int +ACE_RMCast_Fragment<ACE_SYNCH_USE>::put (ACE_Message_Block *mb, + ACE_Time_Value *tv) +{ + // @@ We should keep the total size precomputed + size_t total_size = mb->total_size (); + +#if defined (ACE_HAS_BROKEN_DGRAM_SENDV) + const int TAO_WRITEV_MAX = IOV_MAX - 1; +#else + const int TAO_WRITEV_MAX = IOV_MAX; +#endif /* ACE_HAS_BROKEN_DGRAM_SENDV */ + + const size_t max_fragment_payload = this->max_fragment_size_; + + // Iterate over all the message blocks in the chain. If there is + // enough data to send an MTU then it is sent immediately. + // The last fragment is sent with whatever data remains. + // A single fragment can expand multiple message blocks, put + // together in an <iovec> array, it is also possible that a single + // message block requires multiple fragments... so the code below is + // as simple as possible, but not any simpler ;-) + + + // The first piece of each fragment is a header that contains: + // - A sequence number for reassembly, this is unrelated to + // the sequence number for re-transmission. + // NOTE: yes, this increases the bandwidth requires by 4 bytes on + // each message, I don't think this is a big deal. + // - A fragment offset for reassembly. + // - The total size of the message, so the reassembly layer knows + // when a complete message has been received. + + ACE_UINT32 message_sequence_number; + ACE_UINT32 fragment_offset = 0; + { + ACE_GUARD_RETURN (ACE_SYNCH_MUTEX_T, ace_mon, this->mutex_, -1); + message_sequence_number = ++(this->sequence_number_generator_); + } + + + // The underlying transport layer can only tolerate so many elements + // in a chain, so we must count them and send a fragment if we are + // going over the limit. + + ACE_Message_Block blocks[TAO_WRITEV_MAX]; + + // The first message block contains the fragmentation layer + // header... + ACE_UINT32 header[3]; + header[0] = ACE_HTONL(message_sequence_number); + header[1] = ACE_HTONL(fragment_offset); + header[2] = ACE_HTONL(total_size); + + const size_t fragment_header_size = sizeof(header); + + blocks[0].init (ACE_reinterpret_cast(char*,header), + fragment_header_size); + blocks[0].wr_ptr (fragment_header_size); + + // How many elements of the <blocks> array are in use... + int iovcnt = 1; + + // The size of the current message, adding the size of all its + // message blocks. + size_t fragment_size = fragment_header_size; + + for (ACE_Message_Block* b = mb; b != 0; b = b->cont ()) + { + // Add the block to the vector... + + ACE_Message_Block *last_block = blocks + iovcnt; + + last_block->data_block (b->data_block ()->duplicate ()); + last_block->rd_ptr (b->rd_ptr ()); + last_block->wr_ptr (b->wr_ptr ()); + last_block->cont (0); + // Set the continuation field + blocks[iovcnt - 1].cont (last_block); + + size_t last_block_length = last_block->length (); + + // Recompute the state of the fragment + fragment_size += last_block_length; + iovcnt++; + + while (fragment_size >= max_fragment_payload) + { + // We have filled a fragment. It is possible that we need + // to split the last message block in multiple fragments, + // thus the loop above... + + // First adjust the last message block to exactly fit in the + // fragment: + size_t last_sent_mb_len = + max_fragment_payload - (fragment_size - last_block_length); + + // Send only enough data of the last message block to fill + // the fragment... + last_block->wr_ptr (last_block->rd_ptr () + + last_sent_mb_len); + + if (this->put_next (blocks, tv) == -1) + return -1; + + // adjust the offset + fragment_offset += max_fragment_payload - fragment_header_size; + header[1] = ACE_HTONL(fragment_offset); + + // Now compute how much data is left in the last message + // block, to check if we should continue sending it... + last_block_length -= last_sent_mb_len; + if (last_block_length == 0) + { + // No more data from this message block, just continue + // the outer loop... + iovcnt = 1; + fragment_size = fragment_header_size; + blocks[0].cont (0); + break; // while + } + + // There is some data left, we try to send it in a single + // fragment, if it is still too big the beginning of this + // loop will adjust things. + + // We must put the data in the right place in the array.. + char *rd_ptr = last_block->rd_ptr () + last_sent_mb_len; + char *wr_ptr = rd_ptr + last_block_length; + blocks[1].data_block (last_block->replace_data_block (0)); + + // And determine what segment of the data will be sent.. + blocks[1].rd_ptr (rd_ptr); + blocks[1].wr_ptr (wr_ptr); + blocks[1].cont (0); + last_block = &blocks[1]; + + // Setup the cont field... + blocks[0].cont (last_block); + + // Adjust the state of the fragment + fragment_size = last_block_length + fragment_header_size; + iovcnt = 2; + + // Notice that if <fragment_size> is too big the start of + // this loop will continue the fragmentation. + } + + // It is also possible to fill up the iovec array before the + // fragment is completed, in this case we must send whatever we + // have: + if (iovcnt == TAO_WRITEV_MAX) + { + if (this->put_next (blocks, tv) == -1) + return -1; + + fragment_offset += fragment_size - fragment_header_size; + header[1] = ACE_HTONL(fragment_offset); + iovcnt = 1; + fragment_size = fragment_header_size; + blocks[0].cont (0); + } + } + + if (iovcnt == 1) + return 0; + + return this->put_next (blocks, tv); +} + +#endif /* ACE_RMCAST_FRAGMENT_C */ diff --git a/protocols/ace/RMCast/RMCast_Fragment.h b/protocols/ace/RMCast/RMCast_Fragment.h new file mode 100644 index 00000000000..8aa7024770e --- /dev/null +++ b/protocols/ace/RMCast/RMCast_Fragment.h @@ -0,0 +1,68 @@ +// $Id$ + +// ============================================================================ +// +// = DESCRIPTION +// The fragmentation task for the reliable multicast library +// +// = AUTHOR +// Carlos O'Ryan <coryan@cs.wustl.edu> +// +// ============================================================================ + +#ifndef ACE_RMCAST_FRAGMENT_H +#define ACE_RMCAST_FRAGMENT_H +#include "ace/pre.h" + +#include "RMCast_Export.h" +#include "ace/Task.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#ifndef ACE_RMCAST_DEFAULT_FRAGMENT_SIZE +# define ACE_RMCAST_DEFAULT_FRAGMENT_SIZE 1024 +#endif /* ACE_RMCAST_DEFAULT_FRAGMENT_SIZE */ + +template <ACE_SYNCH_DECL> +class ACE_RMCast_Export ACE_RMCast_Fragment : public ACE_Task<ACE_SYNCH_USE> +{ +public: + ACE_RMCast_Fragment (ACE_Thread_Manager *thr_mgr = 0, + ACE_Message_Queue<ACE_SYNCH_USE> *mq = 0); + // Constructor + + virtual ~ACE_RMCast_Fragment (void); + // Destructor + + size_t max_fragment_size (void) const; + // Accessor for the max_fragment size. + // There is no modifier, the maximum fragment size is obtained using + // feedback from the lower layer (transport?) + + // = The ACE_Task methods + int put (ACE_Message_Block *, ACE_Time_Value *timeout = 0); + +private: + size_t max_fragment_size_; + + ACE_SYNCH_MUTEX_T mutex_; + ACE_UINT32 sequence_number_generator_; + // The sequence number generator +}; + +#if defined (__ACE_INLINE__) +#include "RMCast_Fragment.i" +#endif /* __ACE_INLINE__ */ + +#if defined (ACE_TEMPLATES_REQUIRE_SOURCE) +#include "RMCast_Fragment.cpp" +#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */ + +#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA) +#pragma implementation ("RMCast_Fragment.cpp") +#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */ + +#include "ace/post.h" +#endif /* ACE_RMCAST_FRAGMENT_H */ diff --git a/protocols/ace/RMCast/RMCast_Fragment.i b/protocols/ace/RMCast/RMCast_Fragment.i new file mode 100644 index 00000000000..0cf9f7eea9b --- /dev/null +++ b/protocols/ace/RMCast/RMCast_Fragment.i @@ -0,0 +1,8 @@ +// $Id$ + +template <ACE_SYNCH_DECL> ACE_INLINE size_t +ACE_RMCast_Fragment<ACE_SYNCH_USE>::max_fragment_size (void) const +{ + return this->max_fragment_size_; +} + diff --git a/protocols/ace/RMCast/RMCast_Partial_Message.cpp b/protocols/ace/RMCast/RMCast_Partial_Message.cpp new file mode 100644 index 00000000000..054619d6998 --- /dev/null +++ b/protocols/ace/RMCast/RMCast_Partial_Message.cpp @@ -0,0 +1,180 @@ +// $Id$ + +#include "RMCast_Partial_Message.h" + +#if !defined (__ACE_INLINE__) +#include "RMCast_Partial_Message.i" +#endif /* __ACE_INLINE__ */ + +ACE_RCSID(ace, RMCast_Partial_Message, "$Id$") + +ACE_RMCast_Partial_Message:: +ACE_RMCast_Partial_Message (ACE_UINT32 message_size) + : max_hole_count_ (ACE_RMCAST_DEFAULT_HOLE_COUNT), + hole_count_ (1) +{ + ACE_NEW (this->hole_list_, + ACE_RMCast_Partial_Message::Hole[this->max_hole_count_]); + this->hole_list_[0].start = 0; + this->hole_list_[0].end = message_size; + + this->message_body_.size (message_size); + this->message_body_.wr_ptr (message_size); +} + +ACE_RMCast_Partial_Message:: +~ACE_RMCast_Partial_Message (void) +{ + delete[] this->hole_list_; +} + +int +ACE_RMCast_Partial_Message::fragment_received (ACE_UINT32 message_size, + ACE_UINT32 offset, + ACE_Message_Block *mb) +{ + // Just copy the data... + char *rd_ptr = this->message_body_.rd_ptr () + offset; + size_t total_length = mb->length () - 12; + if (total_length > 0) + { + ACE_OS::memcpy (rd_ptr, + mb->rd_ptr () + 12, + total_length); + rd_ptr += total_length; + } + { + for (const ACE_Message_Block *i = mb->cont (); i != 0; i = i->cont ()) + { + ACE_OS::memcpy (rd_ptr, i->rd_ptr (), i->length ()); + rd_ptr += i->length (); + total_length += i->length (); + } + } + + // The algorithm works like this: + // + // For each hole we determine if there is an intersection between + // the hole and the incoming fragment. If there is none we do + // nothing (actually since the holes are ordered we can stop the + // iteration if the + + ACE_UINT32 start = offset; + ACE_UINT32 end = offset + total_length; + + for (size_t i = 0; i < this->hole_count_; ++i) + { + Hole& hole = this->hole_list_[i]; + + if (end <= hole.start) + return 0; + if (start >= hole.end) + continue; + + // OK there is some intersection. + + // There are only three cases for the <start> value: + // start < hole.start + // start == hole.start + // hole.start < start < hole.end + // + // But the code for both start == hole.start and start < + // hole.start is identical.... + + if (start <= hole.start) + { + if (end < hole.end) + { + // In this case we shrink the hole + hole.start = end; + return 0; + } + else // end >= hole.end + { + // We remove the hole, and continue the iteration... + if (this->remove_hole (i) == -1) + return -1; + continue; + } + } + else // hole.start < start < hole.end + { + if (end >= hole.end) + { + // Just adjust the size of the hole... + hole.start = start; + return 0; + } + else // if (end < hole.end) + { + // Nasty, we need to insert a new hole... + if (this->insert_hole (i, end, hole.end) == -1) + return -1; + // and change the old hole... + // NOTE: we have to refetch it because the array may + // have been reallocated! + this->hole_list_[i].end = start; + continue; + } + } + } + return 0; + // @@ OLD COMMENTS, the algorithm has changed since! + // There are several cases: + // + // 1) The fragment is completely contained in data already received, + // nothing changes in this case. + // + // 2) Part of the fragment is contained in data already received and + // part is new data: + // 2.1) The new data closes a hole, remove it from the list + // 2.2) The beginning of the new fragment is the new data, reduce + // the size of the hole + // 2.3) The end of the new fragment is the new data, increment + // the size of the received block + // + // 3) The fragment is completely contained in a hole + // 3.1) It closes the hole, remove it from the list + // 3.2) It starts at the beginning of a hole, grow the received + // block + // 3.3) It ends at the end of a hole, reduce the hole size + // 3.4) It is in the middle of a hole, insert a new hole + // +} + +int +ACE_RMCast_Partial_Message::insert_hole (size_t i, + ACE_UINT32 start, + ACE_UINT32 end) +{ + if (this->hole_count_ == this->max_hole_count_) + { + this->max_hole_count_ *= 2; + Hole *tmp; + ACE_NEW_RETURN (tmp, Hole[this->max_hole_count_], -1); + for (size_t j = 0; j != this->hole_count_; ++j) + { + tmp[j] = this->hole_list_[j]; + } + } + for (size_t j = this->hole_count_; j != i + 1; --j) + { + this->hole_list_[j] = this->hole_list_[j - 1]; + } + + this->hole_list_[i + 1].start = start; + this->hole_list_[i + 1].end = end; + this->hole_count_++; + + return 0; +} + +int +ACE_RMCast_Partial_Message::remove_hole (size_t i) +{ + for (size_t j = i; j != this->hole_count_ - 1; ++j) + this->hole_list_[j] = this->hole_list_[j + 1]; + + this->hole_count_--; + return 0; +} diff --git a/protocols/ace/RMCast/RMCast_Partial_Message.h b/protocols/ace/RMCast/RMCast_Partial_Message.h new file mode 100644 index 00000000000..af66435825a --- /dev/null +++ b/protocols/ace/RMCast/RMCast_Partial_Message.h @@ -0,0 +1,74 @@ +// $Id$ + +// ============================================================================ +// +// = DESCRIPTION +// Helper class used in the reassembly layer of the realiable +// multicast library. +// +// = AUTHOR +// Carlos O'Ryan <coryan@cs.wustl.edu> +// +// ============================================================================ + +#ifndef ACE_RMCAST_PARTIAL_MESSAGE_H +#define ACE_RMCAST_PARTIAL_MESSAGE_H +#include "ace/pre.h" + +#include "RMCast_Export.h" +#include "ace/Task.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#ifndef ACE_RMCAST_DEFAULT_HOLE_COUNT +#define ACE_RMCAST_DEFAULT_HOLE_COUNT 16 +#endif /* ACE_RMCAST_DEFAULT_HOLE_COUNT */ + +class ACE_RMCast_Export ACE_RMCast_Partial_Message +{ +public: + ACE_RMCast_Partial_Message (ACE_UINT32 message_size); + ~ACE_RMCast_Partial_Message (void); + + int fragment_received (ACE_UINT32 message_size, + ACE_UINT32 offset, + ACE_Message_Block *mb); + int is_complete (void) const; + + ACE_Message_Block *message_body (void); + // Return the body of the message, the memory is owned by the + // class. + +private: + int insert_hole (size_t i, + ACE_UINT32 start, + ACE_UINT32 end); + // Insert a new hole into the list + + int remove_hole (size_t i); + // Remove a hole from the list + +private: + ACE_Message_Block message_body_; + // Used to rebuild the body of the message + + struct Hole + { + ACE_UINT32 start; + ACE_UINT32 end; + }; + + Hole *hole_list_; + size_t max_hole_count_; + size_t hole_count_; + // The current list of holes in the message_body. +}; + +#if defined (__ACE_INLINE__) +#include "RMCast_Partial_Message.i" +#endif /* __ACE_INLINE__ */ + +#include "ace/post.h" +#endif /* ACE_RMCAST_PARTIAL_MESSAGE_H */ diff --git a/protocols/ace/RMCast/RMCast_Partial_Message.i b/protocols/ace/RMCast/RMCast_Partial_Message.i new file mode 100644 index 00000000000..7be89aa1932 --- /dev/null +++ b/protocols/ace/RMCast/RMCast_Partial_Message.i @@ -0,0 +1,15 @@ +// $Id$ + +ACE_INLINE int +ACE_RMCast_Partial_Message::is_complete (void) const +{ + return (this->hole_count_ == 0) + || (this->hole_count_ == 1 + && this->hole_list_[0].start == this->hole_list_[0].end); +} + +ACE_INLINE ACE_Message_Block * +ACE_RMCast_Partial_Message::message_body (void) +{ + return &this->message_body_; +} diff --git a/protocols/ace/RMCast/RMCast_Reassembly.cpp b/protocols/ace/RMCast/RMCast_Reassembly.cpp new file mode 100644 index 00000000000..be56e6cd9e8 --- /dev/null +++ b/protocols/ace/RMCast/RMCast_Reassembly.cpp @@ -0,0 +1,108 @@ +// $Id$ + +#ifndef ACE_RMCAST_REASSEMBLY_C +#define ACE_RMCAST_REASSEMBLY_C + +#include "RMCast_Reassembly.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#include "RMCast_Partial_Message.h" + +#if !defined (__ACE_INLINE__) +#include "RMCast_Reassembly.i" +#endif /* __ACE_INLINE__ */ + +ACE_RCSID(ace, RMCast_Reassembly, "$Id$") + + +template <ACE_SYNCH_DECL> +ACE_RMCast_Reassembly<ACE_SYNCH_USE>:: +ACE_RMCast_Reassembly (ACE_Thread_Manager *thr_mgr, + ACE_Message_Queue<ACE_SYNCH_USE> *mq) + : ACE_Task<ACE_SYNCH_USE> (thr_mgr, mq) +{ +} + +template <ACE_SYNCH_DECL> +ACE_RMCast_Reassembly<ACE_SYNCH_USE>:: +~ACE_RMCast_Reassembly (void) +{ + for (Message_Map_Iterator i = this->messages_.begin (); + i != this->messages_.end (); + ++i) + { + ACE_RMCast_Partial_Message *message = (*i).int_id_; + if (message != 0) + delete message; + } + this->messages_.unbind_all (); +} + +template <ACE_SYNCH_DECL> int +ACE_RMCast_Reassembly<ACE_SYNCH_USE>::put (ACE_Message_Block *mb, + ACE_Time_Value *tv) +{ + ACE_UINT32 header[3]; + size_t fragment_header_size = sizeof(header); + + if (mb->length () < fragment_header_size) + ACE_ERROR_RETURN ((LM_ERROR, + "Message block too small, " + "not enough room for the header\n"), + -1); + + ACE_OS::memcpy (header, mb->rd_ptr (), fragment_header_size); + + ACE_UINT32 message_sequence_number = ACE_NTOHL(header[0]); + ACE_UINT32 offset = ACE_NTOHL(header[1]); + ACE_UINT32 message_size = ACE_NTOHL(header[2]); + + if (mb->length () + offset > message_size) + return -1; // Corrupt message? + + ACE_RMCast_Partial_Message *message; + + { + ACE_GUARD_RETURN (ACE_SYNCH_MUTEX_T, ace_mon, this->mutex_, -1); + if (this->messages_.find (message_sequence_number, message) == -1) + { + ACE_NEW_RETURN (message, + ACE_RMCast_Partial_Message (message_size), + -1); + + if (this->messages_.bind (message_sequence_number, + message) == -1) + return -1; // Internal error? + } + + // The message was in the collection, but it has been received + // already, this is a duplicate fragment, just drop it. + if (message == 0) + return 0; + + if (message->fragment_received (message_size, + offset, + mb) == -1) + return -1; + + if (!message->is_complete ()) + return 0; + + // Remove the message from the collection, but leave a marker + // to indicate that it was already received... + if (this->messages_.rebind (message_sequence_number, 0) == -1) + return -1; + } + + // Push the message... + int r = this->put_next (message->message_body (), tv); + + delete message; + + return r; +} + +#endif /* ACE_RMCAST_REASSEMBLY_C */ diff --git a/protocols/ace/RMCast/RMCast_Reassembly.h b/protocols/ace/RMCast/RMCast_Reassembly.h new file mode 100644 index 00000000000..456c060948a --- /dev/null +++ b/protocols/ace/RMCast/RMCast_Reassembly.h @@ -0,0 +1,67 @@ +// $Id$ + +// ============================================================================ +// +// = DESCRIPTION +// The reassembly task for the reliable multicast library +// +// = AUTHOR +// Carlos O'Ryan <coryan@cs.wustl.edu> +// +// ============================================================================ + +#ifndef ACE_RMCAST_REASSEMBLY_H +#define ACE_RMCAST_REASSEMBLY_H +#include "ace/pre.h" + +#include "RMCast_Export.h" +#include "ace/Task.h" +#include "ace/Hash_Map_Manager.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +class ACE_RMCast_Partial_Message; + +template <ACE_SYNCH_DECL> +class ACE_RMCast_Export ACE_RMCast_Reassembly : public ACE_Task<ACE_SYNCH_USE> +{ +public: + ACE_RMCast_Reassembly (ACE_Thread_Manager *thr_mgr = 0, + ACE_Message_Queue<ACE_SYNCH_USE> *mq = 0); + // Constructor + + virtual ~ACE_RMCast_Reassembly (void); + // Destructor + + // = The ACE_Task methods + int put (ACE_Message_Block *, ACE_Time_Value *timeout = 0); + +private: + ACE_SYNCH_MUTEX_T mutex_; + typedef + ACE_Hash_Map_Manager<ACE_UINT32,ACE_RMCast_Partial_Message*,ACE_Null_Mutex> + Message_Map; + typedef + ACE_Hash_Map_Iterator<ACE_UINT32,ACE_RMCast_Partial_Message*,ACE_Null_Mutex> + Message_Map_Iterator; + + Message_Map messages_; + // The array of partially received messages +}; + +#if defined (__ACE_INLINE__) +#include "RMCast_Reassembly.i" +#endif /* __ACE_INLINE__ */ + +#if defined (ACE_TEMPLATES_REQUIRE_SOURCE) +#include "RMCast_Reassembly.cpp" +#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */ + +#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA) +#pragma implementation ("RMCast_Reassembly.cpp") +#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */ + +#include "ace/post.h" +#endif /* ACE_RMCAST_REASSEMBLY_H */ diff --git a/protocols/ace/RMCast/RMCast_Reassembly.i b/protocols/ace/RMCast/RMCast_Reassembly.i new file mode 100644 index 00000000000..74e88caa0c5 --- /dev/null +++ b/protocols/ace/RMCast/RMCast_Reassembly.i @@ -0,0 +1,2 @@ +// $Id$ + diff --git a/tests/RMCast/Makefile b/tests/RMCast/Makefile new file mode 100644 index 00000000000..3dcc893c67a --- /dev/null +++ b/tests/RMCast/Makefile @@ -0,0 +1,180 @@ +#---------------------------------------------------------------------------- +# +# $Id$ +# +#---------------------------------------------------------------------------- + +#---------------------------------------------------------------------------- +# Local macros +#---------------------------------------------------------------------------- + +BIN = RMCast_Fragment_Test + +PSRC=$(addsuffix .cpp,$(BIN)) +LDLIBS = -lACE_RMCast +CPPFLAGS += -I.. + +#---------------------------------------------------------------------------- +# Include macros and targets +#---------------------------------------------------------------------------- + +include $(ACE_ROOT)/include/makeinclude/wrapper_macros.GNU +include $(ACE_ROOT)/include/makeinclude/macros.GNU +include $(ACE_ROOT)/include/makeinclude/rules.common.GNU +include $(ACE_ROOT)/include/makeinclude/rules.nonested.GNU +include $(ACE_ROOT)/include/makeinclude/rules.bin.GNU +include $(ACE_ROOT)/include/makeinclude/rules.local.GNU + +# To build multiple executables in the same directory on AIX, it works +# best to wipe out any previously-created tempinc directory. +# The compiler/linker isn't too smart about instantiating templates... +ifdef TEMPINCDIR +COMPILE.cc := $(RM) -rf tempinc; $(COMPILE.cc) +endif + +#---------------------------------------------------------------------------- +# Local targets +#---------------------------------------------------------------------------- + +#---------------------------------------------------------------------------- +# Dependencies +#---------------------------------------------------------------------------- +# DO NOT DELETE THIS LINE -- g++dep uses it. +# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. + + +.obj/RMCast_Fragment_Test.o .obj/RMCast_Fragment_Test.so .shobj/RMCast_Fragment_Test.o .shobj/RMCast_Fragment_Test.so: RMCast_Fragment_Test.cpp ../test_config.h \ + $(ACE_ROOT)/ace/pre.h \ + $(ACE_ROOT)/ace/post.h \ + $(ACE_ROOT)/ace/ace_wchar.h \ + $(ACE_ROOT)/ace/ACE_export.h \ + $(ACE_ROOT)/ace/svc_export.h \ + $(ACE_ROOT)/ace/OS.h \ + $(ACE_ROOT)/ace/OS_Dirent.h \ + $(ACE_ROOT)/ace/OS_Dirent.inl \ + $(ACE_ROOT)/ace/Min_Max.h \ + $(ACE_ROOT)/ace/streams.h \ + $(ACE_ROOT)/ace/Basic_Types.h \ + $(ACE_ROOT)/ace/Basic_Types.i \ + $(ACE_ROOT)/ace/Trace.h \ + $(ACE_ROOT)/ace/OS.i \ + $(ACE_ROOT)/ace/Log_Msg.h \ + $(ACE_ROOT)/ace/Log_Record.h \ + $(ACE_ROOT)/ace/Log_Priority.h \ + $(ACE_ROOT)/ace/Log_Record.i \ + $(ACE_ROOT)/ace/Singleton.h \ + $(ACE_ROOT)/ace/Synch.h \ + $(ACE_ROOT)/ace/ACE.h \ + $(ACE_ROOT)/ace/ACE.i \ + $(ACE_ROOT)/ace/SV_Semaphore_Complex.h \ + $(ACE_ROOT)/ace/SV_Semaphore_Simple.h \ + $(ACE_ROOT)/ace/SV_Semaphore_Simple.i \ + $(ACE_ROOT)/ace/SV_Semaphore_Complex.i \ + $(ACE_ROOT)/ace/Synch.i \ + $(ACE_ROOT)/ace/Synch_T.h \ + $(ACE_ROOT)/ace/Event_Handler.h \ + $(ACE_ROOT)/ace/Event_Handler.i \ + $(ACE_ROOT)/ace/Synch_T.i \ + $(ACE_ROOT)/ace/Thread.h \ + $(ACE_ROOT)/ace/Thread.i \ + $(ACE_ROOT)/ace/Atomic_Op.i \ + $(ACE_ROOT)/ace/Synch_T.cpp \ + $(ACE_ROOT)/ace/Singleton.i \ + $(ACE_ROOT)/ace/Singleton.cpp \ + $(ACE_ROOT)/ace/Object_Manager.h \ + $(ACE_ROOT)/ace/Object_Manager.i \ + $(ACE_ROOT)/ace/Managed_Object.h \ + $(ACE_ROOT)/ace/Managed_Object.i \ + $(ACE_ROOT)/ace/Managed_Object.cpp \ + $(ACE_ROOT)/ace/RMCast/RMCast_Fragment.h \ + $(ACE_ROOT)/ace/Task.h \ + $(ACE_ROOT)/ace/Service_Object.h \ + $(ACE_ROOT)/ace/Shared_Object.h \ + $(ACE_ROOT)/ace/Shared_Object.i \ + $(ACE_ROOT)/ace/Service_Object.i \ + $(ACE_ROOT)/ace/Thread_Manager.h \ + $(ACE_ROOT)/ace/Containers.h \ + $(ACE_ROOT)/ace/Malloc_Base.h \ + $(ACE_ROOT)/ace/Containers.i \ + $(ACE_ROOT)/ace/Containers_T.h \ + $(ACE_ROOT)/ace/Containers_T.i \ + $(ACE_ROOT)/ace/Containers_T.cpp \ + $(ACE_ROOT)/ace/Malloc.h \ + $(ACE_ROOT)/ace/Based_Pointer_T.h \ + $(ACE_ROOT)/ace/Based_Pointer_T.i \ + $(ACE_ROOT)/ace/Based_Pointer_T.cpp \ + $(ACE_ROOT)/ace/Based_Pointer_Repository.h \ + $(ACE_ROOT)/ace/Malloc.i \ + $(ACE_ROOT)/ace/Malloc_T.h \ + $(ACE_ROOT)/ace/Free_List.h \ + $(ACE_ROOT)/ace/Free_List.i \ + $(ACE_ROOT)/ace/Free_List.cpp \ + $(ACE_ROOT)/ace/Malloc_T.i \ + $(ACE_ROOT)/ace/Malloc_T.cpp \ + $(ACE_ROOT)/ace/Memory_Pool.h \ + $(ACE_ROOT)/ace/Signal.h \ + $(ACE_ROOT)/ace/Signal.i \ + $(ACE_ROOT)/ace/Mem_Map.h \ + $(ACE_ROOT)/ace/Mem_Map.i \ + $(ACE_ROOT)/ace/Memory_Pool.i \ + $(ACE_ROOT)/ace/Thread_Manager.i \ + $(ACE_ROOT)/ace/Task.i \ + $(ACE_ROOT)/ace/Task_T.h \ + $(ACE_ROOT)/ace/Message_Queue.h \ + $(ACE_ROOT)/ace/Message_Block.h \ + $(ACE_ROOT)/ace/Message_Block.i \ + $(ACE_ROOT)/ace/Message_Block_T.h \ + $(ACE_ROOT)/ace/Message_Block_T.i \ + $(ACE_ROOT)/ace/Message_Block_T.cpp \ + $(ACE_ROOT)/ace/IO_Cntl_Msg.h \ + $(ACE_ROOT)/ace/Message_Queue_T.h \ + $(ACE_ROOT)/ace/Message_Queue_T.i \ + $(ACE_ROOT)/ace/Message_Queue_T.cpp \ + $(ACE_ROOT)/ace/Strategies.h \ + $(ACE_ROOT)/ace/Strategies_T.h \ + $(ACE_ROOT)/ace/Service_Config.h \ + $(ACE_ROOT)/ace/SString.h \ + $(ACE_ROOT)/ace/SString.i \ + $(ACE_ROOT)/ace/Service_Config.i \ + $(ACE_ROOT)/ace/Reactor.h \ + $(ACE_ROOT)/ace/Handle_Set.h \ + $(ACE_ROOT)/ace/Handle_Set.i \ + $(ACE_ROOT)/ace/Timer_Queue.h \ + $(ACE_ROOT)/ace/Timer_Queue_T.h \ + $(ACE_ROOT)/ace/Timer_Queue_T.i \ + $(ACE_ROOT)/ace/Timer_Queue_T.cpp \ + $(ACE_ROOT)/ace/Reactor.i \ + $(ACE_ROOT)/ace/Reactor_Impl.h \ + $(ACE_ROOT)/ace/Svc_Conf_Tokens.h \ + $(ACE_ROOT)/ace/Synch_Options.h \ + $(ACE_ROOT)/ace/Synch_Options.i \ + $(ACE_ROOT)/ace/Hash_Map_Manager.h \ + $(ACE_ROOT)/ace/Functor.h \ + $(ACE_ROOT)/ace/Functor.i \ + $(ACE_ROOT)/ace/Functor_T.h \ + $(ACE_ROOT)/ace/Functor_T.i \ + $(ACE_ROOT)/ace/Functor_T.cpp \ + $(ACE_ROOT)/ace/Hash_Map_Manager_T.h \ + $(ACE_ROOT)/ace/Hash_Map_Manager_T.i \ + $(ACE_ROOT)/ace/Hash_Map_Manager_T.cpp \ + $(ACE_ROOT)/ace/Strategies_T.i \ + $(ACE_ROOT)/ace/Strategies_T.cpp \ + $(ACE_ROOT)/ace/Service_Repository.h \ + $(ACE_ROOT)/ace/Service_Types.h \ + $(ACE_ROOT)/ace/Service_Types.i \ + $(ACE_ROOT)/ace/Service_Repository.i \ + $(ACE_ROOT)/ace/WFMO_Reactor.h \ + $(ACE_ROOT)/ace/WFMO_Reactor.i \ + $(ACE_ROOT)/ace/Strategies.i \ + $(ACE_ROOT)/ace/Message_Queue.i \ + $(ACE_ROOT)/ace/Task_T.i \ + $(ACE_ROOT)/ace/Task_T.cpp \ + $(ACE_ROOT)/ace/Module.h \ + $(ACE_ROOT)/ace/Module.i \ + $(ACE_ROOT)/ace/Module.cpp \ + $(ACE_ROOT)/ace/Stream_Modules.h \ + $(ACE_ROOT)/ace/Stream_Modules.cpp \ + $(ACE_ROOT)/ace/RMCast/RMCast_Fragment.i \ + $(ACE_ROOT)/ace/RMCast/RMCast_Fragment.cpp + +# IF YOU PUT ANYTHING HERE IT WILL GO AWAY diff --git a/tests/RMCast/RMCast_Fragment_Test.cpp b/tests/RMCast/RMCast_Fragment_Test.cpp new file mode 100644 index 00000000000..847d6d91963 --- /dev/null +++ b/tests/RMCast/RMCast_Fragment_Test.cpp @@ -0,0 +1,315 @@ +// $Id$ + +// ============================================================================ +// +// = DESCRIPTION +// Unit test for the fragmentation module of the RMCast library. +// +// = AUTHORS +// Carlos O'Ryan <coryan@uci.edu> +// +// ============================================================================ + +#include "test_config.h" +#include "ace/RMCast/RMCast_Fragment.h" + +ACE_RCSID(tests, RMCast_Fragment_Test, "$Id$") + +class ACE_RMCast_Fragment_Tester : public ACE_Task<ACE_MT_SYNCH> +{ +public: + ACE_RMCast_Fragment_Tester (void); + + virtual int put (ACE_Message_Block *mb, + ACE_Time_Value *tv = 0); + virtual int svc (void); + +private: + void initialize (ACE_Message_Block *mb); + // Initialize the message block with zero data + + int compare (ACE_Message_Block *mb); + // Compare the message block to <received_> + +private: + ACE_RMCast_Fragment<ACE_MT_SYNCH> fragment_; + + ACE_Message_Block received_; + ACE_UINT32 received_bytes_; + ACE_UINT32 message_sequence_number_; +}; + +int +main (int, ACE_TCHAR *[]) +{ + ACE_START_TEST (ACE_TEXT ("RMCast_Fragment_Test")); + + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("This is ACE Version %u.%u.%u\n\n"), + ACE::major_version(), + ACE::minor_version(), + ACE::beta_version())); + + ACE_RMCast_Fragment_Tester tester; + + if (tester.svc () == -1) + ACE_ERROR ((LM_ERROR, "Error running the svc() routine\n")); + + ACE_END_TEST; + return 0; +} + +// **************************************************************** + +ACE_RMCast_Fragment_Tester::ACE_RMCast_Fragment_Tester (void) +{ + this->fragment_.next (this); + this->next (&this->fragment_); +} + +int +ACE_RMCast_Fragment_Tester::svc (void) +{ + { + this->received_.wr_ptr (this->received_.rd_ptr ()); + this->received_bytes_ = 0; + this->message_sequence_number_ = 0; + + ACE_UINT32 n = 128 * 1024; + ACE_Message_Block big_blob (n); + big_blob.wr_ptr (n); + + this->initialize (&big_blob); + + if (this->fragment_.put (&big_blob) == -1) + return -1; + + if (this->received_bytes_ != n) + ACE_ERROR_RETURN ((LM_ERROR, + "Unpexpected number of " + "received bytes (%d/%d)\n", + this->received_bytes_, n), + -1); + + if (this->compare (&big_blob) == -1) + { + ACE_ERROR_RETURN ((LM_ERROR, + "Mismatched big_blob data\n"), + -1); + return -1; + } + + } + + + { + this->received_.wr_ptr (this->received_.rd_ptr ()); + this->received_bytes_ = 0; + this->message_sequence_number_ = 0; + + const int n = 256; + const int size = 512; + ACE_Message_Block small[n]; + small[0].size (size); + small[0].wr_ptr (size); + + for (int i = 1; i != n; ++i) + { + small[i].size (size); + small[i].wr_ptr (size); + small[i - 1].cont (&small[i]); + } + this->initialize (small); + + if (this->fragment_.put (small) == -1) + return -1; + + ACE_UINT32 total = n * size; + if (this->received_bytes_ != total) + ACE_ERROR_RETURN ((LM_ERROR, + "Unpexpected number of " + "received bytes (%d/%d)\n", + this->received_bytes_, total), + -1); + + if (this->compare (small) == -1) + { + ACE_ERROR_RETURN ((LM_ERROR, + "Mismatched small chain data\n"), + -1); + return -1; + } + + } + + { + this->received_.wr_ptr (this->received_.rd_ptr ()); + this->received_bytes_ = 0; + this->message_sequence_number_ = 0; + + const int n = 256; + ACE_UINT32 total = 0; + + ACE_RANDR_TYPE seed = + ACE_static_cast(ACE_RANDR_TYPE,ACE_OS::gethrtime ()); + + int size = 64 + ACE_OS::rand_r(seed) % 128; + ACE_Message_Block small[n]; + small[0].size (size); + small[0].wr_ptr (size); + total += size; + + for (int i = 1; i != n; ++i) + { + size = 64 + ACE_OS::rand_r(seed) % 128; + total += size; + small[i].size (size); + small[i].wr_ptr (size); + small[i - 1].cont (&small[i]); + } + this->initialize (small); + + if (this->fragment_.put (small) == -1) + return -1; + + if (this->received_bytes_ != total) + ACE_ERROR_RETURN ((LM_ERROR, + "Unpexpected number of " + "received bytes (%d/%d)\n", + this->received_bytes_, total), + -1); + + if (this->compare (small) == -1) + { + ACE_ERROR_RETURN ((LM_ERROR, + "Mismatched small chain data\n"), + -1); + return -1; + } + + } + return 0; +} + +void +ACE_RMCast_Fragment_Tester::initialize (ACE_Message_Block *mb) +{ + for (ACE_Message_Block *i = mb; i != 0; i = i->cont ()) + { + char z = 0; + for (char *j = i->rd_ptr (); j != i->wr_ptr (); ++j) + { + *j = ++z; + } + } +} + +int +ACE_RMCast_Fragment_Tester::compare (ACE_Message_Block *mb) +{ + size_t n = mb->total_size (); + ACE_Message_Block blob (n); + + for (const ACE_Message_Block *i = mb; i != 0; i = i->cont ()) + { + blob.copy (i->rd_ptr (), i->length ()); + } + + if (ACE_OS::memcmp (blob.rd_ptr (), + this->received_.rd_ptr (), + n) != 0) + { + for (size_t offset = 0; offset < n; offset += 256) + { + size_t z = 256; + if (n - offset < 256) + z = n - offset; + ACE_HEX_DUMP ((LM_DEBUG, + blob.rd_ptr () + offset, + z, + "BIG BLOB")); + ACE_HEX_DUMP ((LM_DEBUG, + this->received_.rd_ptr () + offset, + z, + "RECEIVED")); + } + return -1; + } + return 0; +} + +int +ACE_RMCast_Fragment_Tester::put (ACE_Message_Block *mb, + ACE_Time_Value *) +{ + ACE_UINT32 header[3]; + size_t fragment_header_size = sizeof(header); + + if (mb->length () < fragment_header_size) + ACE_ERROR_RETURN ((LM_ERROR, + "Message block too small, " + "not enough room for the header\n"), + -1); + + ACE_OS::memcpy (header, mb->rd_ptr (), fragment_header_size); + + ACE_UINT32 message_size = ACE_NTOHL(header[2]); + if (this->received_bytes_ == 0) + { + this->received_.size (message_size); + this->received_.wr_ptr (message_size); + this->message_sequence_number_ = ACE_NTOHL(header[0]); + } + else + { + if (this->message_sequence_number_ != ACE_NTOHL(header[0])) + ACE_ERROR_RETURN ((LM_ERROR, + "Mismatched sequence number\n"), + -1); + if (this->received_.length () != message_size) + ACE_ERROR_RETURN ((LM_ERROR, + "Mismatched sequence size\n"), + -1); + } + + size_t offset = ACE_NTOHL(header[1]); + size_t payload_size = mb->length () - fragment_header_size; + size_t fragment_size = payload_size; + if (payload_size > 0) + { + ACE_OS::memcpy (this->received_.rd_ptr () + offset, + mb->rd_ptr () + fragment_header_size, + payload_size); + this->received_bytes_ += payload_size; + offset += payload_size; + } + + for (const ACE_Message_Block *i = mb->cont (); i != 0; i = i->cont ()) + { + payload_size = i->length (); + // ACE_DEBUG ((LM_DEBUG, + // "offset = %d , payload = %d\n", offset, payload_size)); + fragment_size += payload_size; + ACE_OS::memcpy (this->received_.rd_ptr () + offset, + i->rd_ptr (), payload_size); + this->received_bytes_ += payload_size; + offset += payload_size; + } + + if (fragment_size > this->fragment_.max_fragment_size ()) + ACE_ERROR_RETURN ((LM_ERROR, + "Invalid fragment size\n"), + -1); + + return 0; +} + +#if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION) + +template class ACE_RMCast_Fragment<ACE_MT_SYNCH>; + +#elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA) + +#pragma instantiate ACE_RMCast_Fragment<ACE_MT_SYNCH> + +#endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */ diff --git a/tests/RMCast/RMCast_Fragment_Test.dsp b/tests/RMCast/RMCast_Fragment_Test.dsp new file mode 100644 index 00000000000..3d4e6d49850 --- /dev/null +++ b/tests/RMCast/RMCast_Fragment_Test.dsp @@ -0,0 +1,96 @@ +# Microsoft Developer Studio Project File - Name="RMCast_Fragment_Test" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=RMCast_Fragment_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 "RMCast_Fragment_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 "RMCast_Fragment_Test.mak" CFG="RMCast_Fragment_Test - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "RMCast_Fragment_Test - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "RMCast_Fragment_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)" == "RMCast_Fragment_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 "Release"
+# 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 /MD /W3 /GX /O2 /I "..\.." /I ".." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /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
+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 ace.lib ACE_RMCast.lib /nologo /subsystem:console /machine:I386 /libpath:"..\..\ace" /libpath:"..\..\ace\RMCast"
+
+!ELSEIF "$(CFG)" == "RMCast_Fragment_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 "Debug"
+# 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 /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /I "..\.." /I ".." /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FD /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
+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 ACE_RMCastd.lib aced.lib /nologo /subsystem:console /debug /machine:I386 /out:"RMCast_Fragment_Test.exe" /pdbtype:sept /libpath:"..\..\ace" /libpath:"..\..\ace\RMCast"
+
+!ENDIF
+
+# Begin Target
+
+# Name "RMCast_Fragment_Test - Win32 Release"
+# Name "RMCast_Fragment_Test - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\RMCast_Fragment_Test.cpp
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/tests/RMCast/RMCast_Reassembly_Test.cpp b/tests/RMCast/RMCast_Reassembly_Test.cpp new file mode 100644 index 00000000000..099e1ca6353 --- /dev/null +++ b/tests/RMCast/RMCast_Reassembly_Test.cpp @@ -0,0 +1,287 @@ +// $Id$ + +// ============================================================================ +// +// = DESCRIPTION +// Unit test for the reassembly module of the RMCast library. +// +// = AUTHORS +// Carlos O'Ryan <coryan@uci.edu> +// +// ============================================================================ + +#include "test_config.h" +#include "ace/RMCast/RMCast_Reassembly.h" + +ACE_RCSID(tests, RMCast_Reassembly_Test, "$Id$") + +class ACE_RMCast_Reassembly_Tester : public ACE_Task<ACE_MT_SYNCH> +{ +public: + ACE_RMCast_Reassembly_Tester (void); + + virtual int put (ACE_Message_Block *mb, + ACE_Time_Value *tv = 0); + virtual int svc (void); + +private: + void initialize (ACE_Message_Block *mb); + // Initialize the message block with zero data + + int compare (ACE_Message_Block *received, + ACE_Message_Block *original); + // Compare the message block to <received_> + + int put_fragment (ACE_UINT32 sequence_number, + ACE_UINT32 offset, + ACE_UINT32 fragment_size, + ACE_Message_Block *mb, + ACE_Time_Value *tv); + // Put one fragment out + + ACE_UINT32 next_sequence_number (void); + // Return the next sequence number.. + +private: + ACE_RMCast_Reassembly<ACE_MT_SYNCH> reassembly_; + + ACE_SYNCH_MUTEX mutex_; + ACE_UINT32 message_sequence_number_; +}; + +int +main (int, ACE_TCHAR *[]) +{ + ACE_START_TEST (ACE_TEXT ("RMCast_Reassembly_Test")); + + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("This is ACE Version %u.%u.%u\n\n"), + ACE::major_version(), + ACE::minor_version(), + ACE::beta_version())); + + ACE_RMCast_Reassembly_Tester tester; + + if (tester.activate (THR_NEW_LWP|THR_JOINABLE, 4) == -1) + ACE_ERROR_RETURN ((LM_ERROR, "Cannot activate the threads\n"), 1); + + ACE_Thread_Manager::instance ()->wait (); + + ACE_END_TEST; + return 0; +} + +// **************************************************************** + +ACE_RMCast_Reassembly_Tester::ACE_RMCast_Reassembly_Tester (void) +{ + this->reassembly_.next (this); + this->next (&this->reassembly_); +} + +int +ACE_RMCast_Reassembly_Tester::svc (void) +{ + for (int iteration = 0; iteration != 10; ++iteration) + { + ACE_UINT32 sequence_number = this->next_sequence_number (); + { + ACE_Message_Block received; + + const size_t fragment_size = 128; + ACE_UINT32 n = 256 * fragment_size; + ACE_Message_Block big_blob (n); + big_blob.wr_ptr (n); + + this->initialize (&big_blob); + + // Use an ACT to store the results in <received> + ACE_Message_Block *received_pointer = &received; + ACE_OS::memcpy (big_blob.rd_ptr (), + &received_pointer, + sizeof(received_pointer)); + + for (size_t offset = 0; offset < n; offset += fragment_size) + { + if (this->put_fragment (sequence_number, + offset, + fragment_size, + &big_blob, + 0) == -1) + return -1; + } + + if (this->compare (&received, &big_blob) == -1) + { + ACE_ERROR_RETURN ((LM_ERROR, + "Mismatched big_blob data\n"), + -1); + return -1; + } + } + + sequence_number = this->next_sequence_number (); + { + ACE_Message_Block received; + + const size_t fragment_size = 128; + ACE_UINT32 n = 256 * fragment_size; + ACE_Message_Block big_blob (n); + big_blob.wr_ptr (n); + + this->initialize (&big_blob); + + // Use an ACT to store the results in <received> + ACE_Message_Block *received_pointer = &received; + ACE_OS::memcpy (big_blob.rd_ptr (), + &received_pointer, + sizeof(received_pointer)); + + ACE_RANDR_TYPE seed = ACE_static_cast(ACE_RANDR_TYPE, + ACE_OS::gethrtime ()); + for (int i = 0; i != 100; ++i) + { + size_t offset = ACE_OS::rand_r (seed) % (n - 16); + if (this->put_fragment (sequence_number, + offset, + fragment_size, + &big_blob, + 0) == -1) + return -1; + } + + for (size_t offset = 0; offset < n; offset += fragment_size) + { + if (this->put_fragment (sequence_number, + offset, + fragment_size, + &big_blob, + 0) == -1) + return -1; + } + + if (this->compare (&received, &big_blob) == -1) + { + ACE_ERROR_RETURN ((LM_ERROR, + "Mismatched random big_blob data\n"), + -1); + return -1; + } + } + } + + return 0; +} + +void +ACE_RMCast_Reassembly_Tester::initialize (ACE_Message_Block *mb) +{ + for (ACE_Message_Block *i = mb; i != 0; i = i->cont ()) + { + char z = 0; + for (char *j = i->rd_ptr (); j != i->wr_ptr (); ++j) + { + *j = ++z; + } + } +} + +int +ACE_RMCast_Reassembly_Tester::compare (ACE_Message_Block *received, + ACE_Message_Block *original) +{ + size_t n = original->total_size (); + ACE_Message_Block blob (n); + + for (const ACE_Message_Block *i = original; i != 0; i = i->cont ()) + { + blob.copy (i->rd_ptr (), i->length ()); + } + + if (ACE_OS::memcmp (blob.rd_ptr (), + received->rd_ptr (), + n) != 0) + { + for (size_t offset = 0; offset < n; offset += 256) + { + size_t z = 256; + if (n - offset < 256) + z = n - offset; + ACE_HEX_DUMP ((LM_DEBUG, + blob.rd_ptr () + offset, + z, + "BIG BLOB")); + ACE_HEX_DUMP ((LM_DEBUG, + received->rd_ptr () + offset, + z, + "RECEIVED")); + } + return -1; + } + return 0; +} + +int +ACE_RMCast_Reassembly_Tester::put (ACE_Message_Block *mb, + ACE_Time_Value *) +{ + ACE_Message_Block *pointer; + ACE_OS::memcpy (&pointer, mb->rd_ptr (), sizeof(pointer)); + + size_t l = mb->length (); + pointer->size (l); + pointer->wr_ptr (pointer->rd_ptr () + l); + ACE_OS::memcpy (pointer->rd_ptr (), mb->rd_ptr (), mb->length ()); + return 0; +} + +int +ACE_RMCast_Reassembly_Tester::put_fragment (ACE_UINT32 sequence_number, + ACE_UINT32 offset, + ACE_UINT32 fragment_size, + ACE_Message_Block *mb, + ACE_Time_Value *tv) +{ + size_t total_length = mb->total_length (); + + ACE_UINT32 header[3]; + header[0] = ACE_HTONL(sequence_number); + header[1] = ACE_HTONL(offset); + header[2] = ACE_HTONL(total_length); + + ACE_Message_Block h (ACE_reinterpret_cast(char*,header), + sizeof(header)); + h.wr_ptr (sizeof(header)); + size_t size = fragment_size; + if (total_length - offset < size) + { + size = total_length - offset; + } + ACE_Message_Block p (mb->rd_ptr () + offset, + size); + p.wr_ptr (size); + h.cont (&p); + + return this->reassembly_.put (&h); +} + +ACE_UINT32 +ACE_RMCast_Reassembly_Tester::next_sequence_number () +{ + ACE_UINT32 r; + { + ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, ace_mon, this->mutex_, 0); + r = this->message_sequence_number_++; + } + return r; +} + +#if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION) + +template class ACE_RMCast_Reassembly<ACE_MT_SYNCH>; + +#elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA) + +#pragma instantiate ACE_RMCast_Reassembly<ACE_MT_SYNCH> + +#endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */ diff --git a/tests/RMCast/RMCast_Reassembly_Test.dsp b/tests/RMCast/RMCast_Reassembly_Test.dsp new file mode 100644 index 00000000000..6a617c44754 --- /dev/null +++ b/tests/RMCast/RMCast_Reassembly_Test.dsp @@ -0,0 +1,96 @@ +# Microsoft Developer Studio Project File - Name="RMCast_Reassembly_Test" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=RMCast_Reassembly_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 "RMCast_Reassembly_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 "RMCast_Reassembly_Test.mak" CFG="RMCast_Reassembly_Test - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "RMCast_Reassembly_Test - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "RMCast_Reassembly_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)" == "RMCast_Reassembly_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 "Release"
+# 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 /MD /W3 /GX /O2 /I "..\.." /I ".." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /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
+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 ace.lib ACE_RMCast.lib /nologo /subsystem:console /machine:I386 /libpath:"..\..\ace" /libpath:"..\..\ace\RMCast"
+
+!ELSEIF "$(CFG)" == "RMCast_Reassembly_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 "Debug"
+# 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 /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /I "..\.." /I ".." /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FD /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
+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 ACE_RMCastd.lib aced.lib /nologo /subsystem:console /debug /machine:I386 /out:"RMCast_Reassembly_Test.exe" /pdbtype:sept /libpath:"..\..\ace" /libpath:"..\..\ace\RMCast"
+
+!ENDIF
+
+# Begin Target
+
+# Name "RMCast_Reassembly_Test - Win32 Release"
+# Name "RMCast_Reassembly_Test - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\RMCast_Reassembly_Test.cpp
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/tests/RMCast/RMCast_Tests.dsw b/tests/RMCast/RMCast_Tests.dsw new file mode 100644 index 00000000000..7471a20220b --- /dev/null +++ b/tests/RMCast/RMCast_Tests.dsw @@ -0,0 +1,41 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "RMCast_Fragment_Test"=.\RMCast_Fragment_Test.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "RMCast_Reassembly_Test"=.\RMCast_Reassembly_Test.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
|