summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcoryan <coryan@ae88bc3d-4319-0410-8dbf-d08b4c9d3795>2000-06-17 00:39:09 +0000
committercoryan <coryan@ae88bc3d-4319-0410-8dbf-d08b4c9d3795>2000-06-17 00:39:09 +0000
commit9858d5181a243af42a9a15048e0bf7db4928f94c (patch)
tree8c598bbe84a843f5eb9b5fd895ba1acafa128f47
parent6107fcba7504cca59cc0b9d85286b73507e3897e (diff)
downloadATCD-9858d5181a243af42a9a15048e0bf7db4928f94c.tar.gz
ChangeLogTag:Fri Jun 16 17:30:18 2000 Carlos O'Ryan <coryan@uci.edu>
-rw-r--r--ChangeLog149
-rw-r--r--ChangeLogs/ChangeLog-02a149
-rw-r--r--ChangeLogs/ChangeLog-03a149
-rw-r--r--ace/RMCast/Makefile40
-rw-r--r--ace/RMCast/RMCast.dsp151
-rw-r--r--ace/RMCast/RMCast.dsw29
-rw-r--r--ace/RMCast/RMCast_Export.h40
-rw-r--r--ace/RMCast/RMCast_Fragment.cpp204
-rw-r--r--ace/RMCast/RMCast_Fragment.h68
-rw-r--r--ace/RMCast/RMCast_Fragment.i8
-rw-r--r--ace/RMCast/RMCast_Partial_Message.cpp180
-rw-r--r--ace/RMCast/RMCast_Partial_Message.h74
-rw-r--r--ace/RMCast/RMCast_Partial_Message.i15
-rw-r--r--ace/RMCast/RMCast_Reassembly.cpp108
-rw-r--r--ace/RMCast/RMCast_Reassembly.h67
-rw-r--r--ace/RMCast/RMCast_Reassembly.i2
-rw-r--r--protocols/ace/RMCast/Makefile40
-rw-r--r--protocols/ace/RMCast/RMCast.dsp151
-rw-r--r--protocols/ace/RMCast/RMCast.dsw29
-rw-r--r--protocols/ace/RMCast/RMCast_Export.h40
-rw-r--r--protocols/ace/RMCast/RMCast_Fragment.cpp204
-rw-r--r--protocols/ace/RMCast/RMCast_Fragment.h68
-rw-r--r--protocols/ace/RMCast/RMCast_Fragment.i8
-rw-r--r--protocols/ace/RMCast/RMCast_Partial_Message.cpp180
-rw-r--r--protocols/ace/RMCast/RMCast_Partial_Message.h74
-rw-r--r--protocols/ace/RMCast/RMCast_Partial_Message.i15
-rw-r--r--protocols/ace/RMCast/RMCast_Reassembly.cpp108
-rw-r--r--protocols/ace/RMCast/RMCast_Reassembly.h67
-rw-r--r--protocols/ace/RMCast/RMCast_Reassembly.i2
-rw-r--r--tests/RMCast/Makefile180
-rw-r--r--tests/RMCast/RMCast_Fragment_Test.cpp315
-rw-r--r--tests/RMCast/RMCast_Fragment_Test.dsp96
-rw-r--r--tests/RMCast/RMCast_Reassembly_Test.cpp287
-rw-r--r--tests/RMCast/RMCast_Reassembly_Test.dsp96
-rw-r--r--tests/RMCast/RMCast_Tests.dsw41
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>
+{{{
+}}}
+
+###############################################################################
+