diff options
Diffstat (limited to 'docs/tutorials/015')
49 files changed, 0 insertions, 5436 deletions
diff --git a/docs/tutorials/015/015-client.dsp b/docs/tutorials/015/015-client.dsp deleted file mode 100644 index 5152df92235..00000000000 --- a/docs/tutorials/015/015-client.dsp +++ /dev/null @@ -1,138 +0,0 @@ -# Microsoft Developer Studio Project File - Name="015 client" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Console Application" 0x0103
-
-CFG=015 client - 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 "015-client.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 "015-client.mak" CFG="015 client - Win32 Debug"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "015 client - Win32 Release" (based on\
- "Win32 (x86) Console Application")
-!MESSAGE "015 client - Win32 Debug" (based on\
- "Win32 (x86) Console Application")
-!MESSAGE
-
-# Begin Project
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-RSC=rc.exe
-
-!IF "$(CFG)" == "015 client - 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 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 "..\..\.." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-# ADD LINK32 ace.lib /nologo /subsystem:console /machine:I386 /libpath:"..\..\..\ace"
-
-!ELSEIF "$(CFG)" == "015 client - 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 /GX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MDd /W3 /GX /Od /I "..\..\.." /D "WIN32" /D "_DEBUG" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "_DEBUG"
-# ADD RSC /l 0x409 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 aced.lib /nologo /subsystem:console /debug /machine:I386 /out:"../client.exe" /pdbtype:sept /libpath:"..\..\..\ace"
-
-!ENDIF
-
-# Begin Target
-
-# Name "015 client - Win32 Release"
-# Name "015 client - Win32 Debug"
-# Begin Group "Source Files"
-
-# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
-# Begin Source File
-
-SOURCE=client.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=Client_i.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=Compressor.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=Crypt.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=Protocol_Stream.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=Protocol_Task.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=Recv.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=Xmit.cpp
-# End Source File
-# End Group
-# Begin Group "Header Files"
-
-# PROP Default_Filter "h;hpp;hxx;hm;inl"
-# Begin Source File
-
-SOURCE=Client_i.h
-# End Source File
-# Begin Source File
-
-SOURCE=Protocol_Stream.h
-# End Source File
-# End Group
-# Begin Group "Resource Files"
-
-# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
-# End Group
-# End Target
-# End Project
diff --git a/docs/tutorials/015/015-server.dsp b/docs/tutorials/015/015-server.dsp deleted file mode 100644 index d9f45886fe9..00000000000 --- a/docs/tutorials/015/015-server.dsp +++ /dev/null @@ -1,166 +0,0 @@ -# Microsoft Developer Studio Project File - Name="015 server" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Console Application" 0x0103
-
-CFG=015 server - 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 "015-server.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 "015-server.mak" CFG="015 server - Win32 Debug"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "015 server - Win32 Release" (based on\
- "Win32 (x86) Console Application")
-!MESSAGE "015 server - Win32 Debug" (based on\
- "Win32 (x86) Console Application")
-!MESSAGE
-
-# Begin Project
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-RSC=rc.exe
-
-!IF "$(CFG)" == "015 server - 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 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 "..\..\.." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-# ADD LINK32 ace.lib /nologo /subsystem:console /machine:I386 /libpath:"..\..\..\ace"
-
-!ELSEIF "$(CFG)" == "015 server - 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 /GX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MDd /W3 /GX /Od /I "..\..\.." /D "WIN32" /D "_DEBUG" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "_DEBUG"
-# ADD RSC /l 0x409 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 aced.lib /nologo /subsystem:console /debug /machine:I386 /out:"../server.exe" /pdbtype:sept /libpath:"..\..\..\ace"
-
-!ENDIF
-
-# Begin Target
-
-# Name "015 server - Win32 Release"
-# Name "015 server - Win32 Debug"
-# Begin Group "Source Files"
-
-# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
-# Begin Source File
-
-SOURCE=Compressor.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=Crypt.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=Handler.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=Protocol_Stream.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=Protocol_Task.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=Recv.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=server.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=Server_i.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=Xmit.cpp
-# End Source File
-# End Group
-# Begin Group "Header Files"
-
-# PROP Default_Filter "h;hpp;hxx;hm;inl"
-# Begin Source File
-
-SOURCE=Compressor.h
-# End Source File
-# Begin Source File
-
-SOURCE=Crypt.h
-# End Source File
-# Begin Source File
-
-SOURCE=Handler.h
-# End Source File
-# Begin Source File
-
-SOURCE=Protocol_Stream.h
-# End Source File
-# Begin Source File
-
-SOURCE=Protocol_Task.h
-# End Source File
-# Begin Source File
-
-SOURCE=Recv.h
-# End Source File
-# Begin Source File
-
-SOURCE=Server_i.h
-# End Source File
-# Begin Source File
-
-SOURCE=Xmit.h
-# End Source File
-# End Group
-# Begin Group "Resource Files"
-
-# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
-# End Group
-# End Target
-# End Project
diff --git a/docs/tutorials/015/Client_i.cpp b/docs/tutorials/015/Client_i.cpp deleted file mode 100644 index 6415fed1966..00000000000 --- a/docs/tutorials/015/Client_i.cpp +++ /dev/null @@ -1,60 +0,0 @@ - -// $Id$ - -#include "Client_i.h" -#include "ace/Message_Block.h" -#include "ace/INET_Addr.h" -#include "ace/SOCK_Connector.h" - -// Simple constructor just remembers the endpoint information for use by open. -Client::Client( u_short _port, const char * _server) - : port_(_port), server_(_server) -{ - ; -} - -/* Do nothing. This should probably call close() if we can make sure - that it's OK to close() multiple times. -*/ -Client::~Client(void) -{ - ; -} - -/* Open the connection to the server. This is traditional ACE. We - simply construct an endpoint and use a connector to establish the - link. -*/ -int Client::open( void ) -{ - ACE_INET_Addr addr(port_,server_); - ACE_SOCK_Connector con; - - if( con.connect(peer(),addr) == -1 ) - { - ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "ACE_SOCK_Connector::connect()"), -1); - } - - // Something new here... We have to use the protocol stream - // to ensure that our data is in the correct format when - // received by the server. Thus, we open the stream and - // transfer ownership of the peer. - return stream().open( peer() ); -} - -// The remainder of the functions just delegate to the stream. - -int Client::close( void ) -{ - return stream().close(); -} - -int Client::put( ACE_Message_Block * _message ) -{ - return stream().put(_message,0); -} - -int Client::get( ACE_Message_Block * & _response ) -{ - return stream().get(_response); -} diff --git a/docs/tutorials/015/Client_i.h b/docs/tutorials/015/Client_i.h deleted file mode 100644 index 32eaac8dd48..00000000000 --- a/docs/tutorials/015/Client_i.h +++ /dev/null @@ -1,73 +0,0 @@ -// $Id$ - -#ifndef CLIENT_H -#define CLIENT_H - -#include "ace/SOCK_Stream.h" - -#if !defined (ACE_LACKS_PRAGMA_ONCE) -# pragma once -#endif /* ACE_LACKS_PRAGMA_ONCE */ - -#include "Protocol_Stream.h" - -class ACE_Message_Block; - -/* Hide the details of connection and protocol-conformance from the - application-level logic. -*/ -class Client -{ -public: - // Provide the server information when constructing the - // object. This could (and probably should) be moved to the - // open() method. - Client (u_short port, - const char *server); - - // Cleanup... - ~Client (void); - - // Open the connection to the server. - int open (void); - - // Close the connection to the server. Be sure to do this - // before you let the Client go out of scope. - int close (void); - - // Put a message to the server. The Client assumes ownership of - // <message> at that point and will release() it when done. Do not - // use <message> after passing it to put(). - int put (ACE_Message_Block *message); - - // Get a response from the server. The caller becomes the owner of - // <response> after this call and is responsible for invoking - // release() when done. - int get (ACE_Message_Block *&response); - -private: - // Protocol_Stream hides the protocol conformance details from us. - Protocol_Stream stream_; - - // We create a connection on the peer_ and then pass ownership of it - // to the protocol stream. - ACE_SOCK_Stream peer_; - - // Endpoing information saved by the constructor for use by open(). - u_short port_; - const char *server_; - - // Accessors for the complex member variables. - - Protocol_Stream &stream (void) - { - return this->stream_; - } - - ACE_SOCK_Stream &peer (void) - { - return this->peer_; - } -}; - -#endif /* CLIENT_H */ diff --git a/docs/tutorials/015/Compressor.cpp b/docs/tutorials/015/Compressor.cpp deleted file mode 100644 index 931264d716c..00000000000 --- a/docs/tutorials/015/Compressor.cpp +++ /dev/null @@ -1,93 +0,0 @@ - -// $Id$ - -#include "Compressor.h" -#include "ace/SOCK_Stream.h" - -Compressor::Compressor( void ) - : Protocol_Task() -{ - ; -} - -Compressor::~Compressor(void) -{ - ; -} - -/* This is where you insert your compression code. Most compressors - want to work on a block of data instead of a byte-stream. - Fortunately the message block has a block that can be compressed. - Take a look at libz for a quick way to add compression to your - apps - */ -int Compressor::send(ACE_Message_Block *message, ACE_Time_Value *timeout) -{ - ACE_DEBUG ((LM_INFO, "(%P|%t) Compressor::send() compressing (%s)\n", message->rd_ptr() )); - - // Create a block to hold the compressed data. I belive libz - // recommends a buffer about 10-20% larger than the source. - // Other libraries/algorithms may have their own quirks. - ACE_Message_Block * compressed = new ACE_Message_Block( message->size() ); - - // Perform a bogus compression algorithm. 'CD' just tells me - // that this is compressed data and when we "decompress" we'll - // look for this signature to validate the data received. - ACE_OS::sprintf( compressed->wr_ptr(), "CD:%s", message->rd_ptr() ); - compressed->wr_ptr( strlen(compressed->wr_ptr())+1 ); - - // Send the compressed data down the stream to the next module - this->put_next( compressed ); - - // We're done here. - message->release(); - - return( 0 ); -} - -/* And here's the decompression side. We've written Xmit/Recv so that - we're guaranteed to get an entire block of compressed data. If - we'd used recv() in the Recv object then we might have gotten a - partial block and that may not decompress very nicely. - */ -int Compressor::recv(ACE_Message_Block *message, ACE_Time_Value *timeout) -{ - ACE_DEBUG ((LM_INFO, "(%P|%t) Compress::recv() decompressing (%s)\n", message->rd_ptr() )); - - // Room for the decompressed data. In the real world you - // would probably want to send the original (uncompressed) - // data size in the message. You can predict the maximum - // possible decompression size but it's cheap and easy just to - // send that along. Look again at how I do exacly that - // between Xmit and Recv. - ACE_Message_Block * decompressed = new ACE_Message_Block( message->size() ); - - // Check for our signature. Even when you use a real - // compression algorithm you may want to include your own - // signature so that you can verify the block. It pays to be - // paranoid! - if( ACE_OS::strncmp( message->rd_ptr(), "CD:", 3 ) ) - { - ACE_DEBUG ((LM_INFO, "(%P|%t) Improperly encompressed data.\n" )); - message->release(); - return(-1); - } - - // Skip past the signature before going any further. - message->rd_ptr( 3 ); - - // Perform a bogus decompression algorithm. This is where you - // would feed to libz or your favorite decompressor. (It's - // costly but you could invoke popen() on gzip!) - ACE_OS::sprintf( decompressed->wr_ptr(), "%s", message->rd_ptr() ); - decompressed->wr_ptr( strlen(decompressed->wr_ptr())+1 ); - - // Recv the decompressed data down the stream to the next module - this->put_next( decompressed ); - - // We're done here. - message->release(); - - return( 0 ); -} - diff --git a/docs/tutorials/015/Compressor.h b/docs/tutorials/015/Compressor.h deleted file mode 100644 index cb4c7248cce..00000000000 --- a/docs/tutorials/015/Compressor.h +++ /dev/null @@ -1,35 +0,0 @@ -// $Id$ - -#ifndef COMPRESSOR_H -#define COMPRESSOR_h - -#include "Protocol_Task.h" - -/* A reallly dumb compression object. (It actually adds 3 bytes to - every message block.) -*/ -class Compressor : public Protocol_Task -{ -public: - - typedef Protocol_Task inherited; - - Compressor (void); - - ~Compressor (void); - -protected: - - // This is called when the compressor is on the downstream side. - // We'll take the message, compress it and move it along to the next - // module. - int send (ACE_Message_Block *message, - ACE_Time_Value *timeout); - - // This one is called on the upstream side. No surprise: we - // decompress the data and send it on up the stream. - int recv (ACE_Message_Block *message, - ACE_Time_Value *timeout); -}; - -#endif /* COMPRESSOR_H */ diff --git a/docs/tutorials/015/Crypt.cpp b/docs/tutorials/015/Crypt.cpp deleted file mode 100644 index 83cfd7ab73f..00000000000 --- a/docs/tutorials/015/Crypt.cpp +++ /dev/null @@ -1,77 +0,0 @@ - -// $Id$ - -#include "Crypt.h" -#include "ace/SOCK_Stream.h" - -/* The expected constructor... - */ -Crypt::Crypt( void ) - : Protocol_Task() -{ -} - -Crypt::~Crypt(void) -{ -} - -/* To send the data we'll apply a signature and encryption. - */ -int Crypt::send(ACE_Message_Block *message, ACE_Time_Value *timeout) -{ - ACE_DEBUG ((LM_INFO, "(%P|%t) Crypt::send() encrypting (%s)\n", message->rd_ptr() )); - - // I suspect that some encryptors might change the data size. - // It probably isn't safe to create a same-size destination buffer. - ACE_Message_Block * encrypted = new ACE_Message_Block( message->size() ); - - // Perform a bogus encryption algorithm and add our safety - // signature. Adding the original data size is also probably - // a good idea that I haven't encorporated here. - ACE_OS::sprintf( encrypted->wr_ptr(), "ED:%s", message->rd_ptr() ); - encrypted->wr_ptr( strlen(encrypted->wr_ptr())+1 ); - - // Send the encrypted data down the stream to the next module - this->put_next( encrypted ); - - // We're done here. - message->release(); - - return( 0 ); -} - -/* The upstream movement requires that we decrypt what the peer has - given us. -*/ -int Crypt::recv(ACE_Message_Block *message, ACE_Time_Value *timeout) -{ - ACE_DEBUG ((LM_INFO, "(%P|%t) Crypt::recv() decrypting (%s)\n", message->rd_ptr() )); - - // Create a destination for the decrypted data. The same - // block size caveat exists of course. - ACE_Message_Block * decrypted = new ACE_Message_Block( message->size() ); - - // Check the signature as expected. - if( ACE_OS::strncmp( message->rd_ptr(), "ED:", 3 ) ) - { - ACE_DEBUG ((LM_INFO, "(%P|%t) Improperly encrypted data.\n" )); - message->release(); - return(-1); - } - - // Don't forget to skip past the signature before decrypting - // or things will be quite exciting! - message->rd_ptr( 3 ); - - // Perform a bogus decryption algorithm - ACE_OS::sprintf( decrypted->wr_ptr(), "%s", message->rd_ptr() ); - decrypted->wr_ptr( strlen(decrypted->wr_ptr())+1 ); - - // Send the decrypted data down the stream to the next module - this->put_next( decrypted ); - - // We're done here. - message->release(); - - return( 0 ); -} diff --git a/docs/tutorials/015/Crypt.h b/docs/tutorials/015/Crypt.h deleted file mode 100644 index 6de997fa4a9..00000000000 --- a/docs/tutorials/015/Crypt.h +++ /dev/null @@ -1,32 +0,0 @@ -// $Id$ - -#ifndef CRYPT_H -#define CRYPT_h - -#include "Protocol_Task.h" - -/* An interface (adaptor) between your favorite encryption method and - an ACE_Stream. -*/ -class Crypt : public Protocol_Task -{ -public: - - typedef Protocol_Task inherited; - - Crypt (void); - - ~Crypt (void); - -protected: - - // Moving downstream will encrypt the data - int send (ACE_Message_Block *message, - ACE_Time_Value *timeout); - - // And moving upstream will decrypt it. - int recv (ACE_Message_Block *message, - ACE_Time_Value *timeout); -}; - -#endif /* CRYPT_H */ diff --git a/docs/tutorials/015/Handler.cpp b/docs/tutorials/015/Handler.cpp deleted file mode 100644 index 0cfb3242c3d..00000000000 --- a/docs/tutorials/015/Handler.cpp +++ /dev/null @@ -1,179 +0,0 @@ - -// $Id$ - -#include "Handler.h" -#include "Protocol_Task.h" - -/* The Protocol_Stream gives us the option to insert a Protocol_Task - to process data received by the stream. We'll get into the details - more when we talk about the stream in detail. For now it's enough - to know that Handler_Task::recv() will be invoked by the stream - after data from the client has been received and processed (eg -- - decrypted, uncompressed, and whatever else the protocol requires.) -*/ -class Handler_Task : public Protocol_Task -{ -public: - - // Typical... - typedef Protocol_Task inherited; - - // Simple... - Handler_Task(void); - ~Handler_Task(void); - -protected: - - // recv() is invoked after received data has been fully - // processed by the protocol rules. Data processing typically - // done in handle_input() can then be done here. - int recv(ACE_Message_Block * message, - ACE_Time_Value *timeout = 0); -}; - -Handler::Handler(void) -{ - ; -} - -Handler::~Handler(void) -{ - ; -} - -/* The Acceptor will open() us once the peer() connection is - established. There are a couple of things we have to do here - before we're ready to receive data from the client. -*/ -int Handler::open (void *) -{ - ACE_INET_Addr addr; - - // Make sure that we can get the peer's address. If we can't - // then there may be a network error or something else that - // will prevent communicating with the client. This is - // something you'll want to do in every event handler you create. - if (this->peer ().get_remote_addr (addr) == -1) - ACE_ERROR_RETURN ((LM_ERROR, "(%P|%t) Cannot get remote addr\n"), -1); - - // Announce the client - ACE_DEBUG ((LM_DEBUG, "(%P|%t) connected with %s\n", addr.get_host_name() )); - - // Here's the first new twist to the old event handler. - // Before we can use the Protocol_Stream to communicate with - // the peer, we must open() it. We provide the stream with - // the peer() so that it will have a valid socket on which to - // read client requests and send our responses. We also - // provide a Handler_Task instance that will ultimately be - // responsible for processing any client data we receive. - int rval = stream().open( this->peer(), new Handler_Task() ); - - // Of course, we have to account for the chance that the - // stream's open() may fail. - if( rval == -1 ) - { - ACE_ERROR_RETURN ((LM_ERROR, "(%P|%t) Cannot open the protocol stream.\n"), -1); - } - - // Now that we know the client is valid and that the stream is - // ready for business we can register with the gloabl reactor - // instance. Here again is an opportunity for improvement if - // we expect to have mulitple Server object instances. - if (ACE_Reactor::instance()->register_handler (this, ACE_Event_Handler::READ_MASK) == -1) - ACE_ERROR_RETURN ((LM_ERROR, "(%P|%t) Cannot register with reactor\n"), -1); - - return rval; -} - -/* This is a fairly typical destroy() method that can be shared by - both close() and handle_close(). -*/ -void Handler::destroy (void) -{ - ACE_Reactor::instance()->remove_handler(this,ACE_Event_Handler::READ_MASK|ACE_Event_Handler::DONT_CALL); - - this->peer ().close (); - - delete this; -} - -/* In this simple application we just forward the close() and - handle_close() requests right on to the destroy() method. -*/ - -int Handler::close (u_long) -{ - this->destroy (); - return 0; -} - -int Handler::handle_close(ACE_HANDLE, ACE_Reactor_Mask _mask) -{ - this->destroy(); - return 0; -} - -/* Unlike a "traditional" handle_input() ours is very simple. Because - of the use of the protocol stream, we delegate the read function to - the stream's get() and rely on our Handler_Task to do the real work. -*/ -int Handler::handle_input (ACE_HANDLE) -{ - ACE_DEBUG ((LM_DEBUG, "(%P|%t) Activity from client\n" )); - - // This will cause a blocking read from the peer(). The data - // will then be pushed through the protocol stream. - if( stream().get( ) == -1 ) - { - ACE_ERROR_RETURN ((LM_ERROR, "(%P|%t) Cannot get data from protocol stream\n"), -1); - } - - return 0; -} - -/* A Protocol_Task is derived from ACE_Task and has the option of - running in one or more threads. I've chosen here to construct the - baseclass with no threads but it should work just fine with one or - more if you need. Unless you're sharing the Handler_Task with - several peers, however, you're probably just wasting a thread to - activate it. On the other hand, if your reactor is running in a - single thread (as in this example) then you can easily implement - thread-per-connection concurrency by giving the baseclass one thread. -*/ -Handler_Task::Handler_Task(void) - : inherited() -{ - ; -} - -Handler_Task::~Handler_Task(void) -{ - ; -} - -/* When installed into the protocol stream, the Handler_Task's recv() - method will be called when data is ready for processing. - */ -int Handler_Task::recv(ACE_Message_Block * message, - ACE_Time_Value *timeout ) -{ - // Announce the request we got from the client - ACE_DEBUG ((LM_INFO, "(%P|%t) Handler_Task::recv() got (%s)\n", message->rd_ptr() )); - - // Create a response message to send to the client - ACE_Message_Block * response = new ACE_Message_Block( 128 ); - - // Nothing very original about this I'm afraid... - ACE_OS::sprintf( response->wr_ptr(), "You Said: (%s)", message->rd_ptr() ); - response->wr_ptr( strlen(response->wr_ptr())+1 ); - - // Release the original message block now that we're through - // "processing" it. - message->release(); - - // Turn the message around and send it back down the Stream. - // In other words, we invoke the put() method on the - // Protocol_Stream without having to have a direct reference - // to the stream object. - return this->reply( response, timeout ); -} diff --git a/docs/tutorials/015/Handler.h b/docs/tutorials/015/Handler.h deleted file mode 100644 index 1a0f1a69e46..00000000000 --- a/docs/tutorials/015/Handler.h +++ /dev/null @@ -1,61 +0,0 @@ -// $Id$ - -#ifndef HANDLER_H -#define HANDLER_H - -#include "ace/Svc_Handler.h" - -#if !defined (ACE_LACKS_PRAGMA_ONCE) -# pragma once -#endif /* ACE_LACKS_PRAGMA_ONCE */ - -#include "ace/SOCK_Stream.h" -#include "Protocol_Stream.h" - -/* Just your basic event handler. We use ACE_Svc_Handler<> as a - baseclass so that it can maintain the peer() and other details for - us. We're not going to activate() this object, so we can get away - with the NULL synch choice. */ -class Handler : public ACE_Svc_Handler <ACE_SOCK_STREAM, ACE_NULL_SYNCH> -{ -public: - Handler (void); - ~Handler (void); - - // Called by the acceptor when we're created in response to a client - // connection. - int open (void *); - - // Called when it's time for us to be deleted. We take care of - // removing ourselves from the reactor and shutting down the peer() - // connectin. - void destroy (void); - - // Called when it's time for us to go away. There are subtle - // differences between destroy() and close() so don't try to use - // either for all cases. - int close (u_long); - -protected: - // Respond to peer() activity. - int handle_input (ACE_HANDLE); - - // This will be called when handle_input() returns a failure code. - // That's our signal that it's time to begin the shutdown process. - int handle_close (ACE_HANDLE, - ACE_Reactor_Mask mask); -private: - - // Like the Client, we have to abide by the protocol requirements. - // We use a local Protocol_Stream object to take care of those - // details. For us, I/O then just becomes a matter of interacting - // with the stream. - Protocol_Stream stream_; - - Protocol_Stream &stream (void) - { - return this->stream_; - } -}; - -#endif /* HANDLER_H */ diff --git a/docs/tutorials/015/Makefile b/docs/tutorials/015/Makefile deleted file mode 100644 index 5975764d91d..00000000000 --- a/docs/tutorials/015/Makefile +++ /dev/null @@ -1,33 +0,0 @@ - -# $Id$ - -#---------------------------------------------------------------------------- -# Local macros -#---------------------------------------------------------------------------- - -BIN = client server - -all clean realclean : # - $(MAKE) -f Makefile.client $@ - $(MAKE) -f Makefile.server $@ - -client server : # - $(MAKE) -f Makefile.$@ all - -Depend : # - $(MAKE) -f Makefile.client $@ - -HTML : # - [ -f hdr ] || $(MAKE) UNSHAR - perl ../combine *.pre - chmod +r *.html - -SHAR : # - [ ! -f combine.shar ] || exit 1 - shar -T hdr bodies *.pre *.pst > combine.shar && $(RM) hdr bodies *.pre *.pst - -UNSHAR : # - sh combine.shar - -CLEAN : realclean - $(RM) hdr bodies *.pre *.pst .depend* diff --git a/docs/tutorials/015/Makefile.client b/docs/tutorials/015/Makefile.client deleted file mode 100644 index 20680aea15b..00000000000 --- a/docs/tutorials/015/Makefile.client +++ /dev/null @@ -1,79 +0,0 @@ - -# $Id$ - -#---------------------------------------------------------------------------- -# Local macros -#---------------------------------------------------------------------------- - -BIN = client - -FILES += Protocol_Stream -FILES += Protocol_Task -FILES += Xmit -FILES += Recv -FILES += Compressor -FILES += Crypt -FILES += Client_i - -BUILD = $(VBIN) - -SRC = $(addsuffix .cpp,$(BIN)) -SRC += $(addsuffix .cpp,$(FILES)) - -HDR = *.h - -MAKEFILE = Makefile.client -DEPEND = .depend.client - -#---------------------------------------------------------------------------- -# 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.lib.GNU -include $(ACE_ROOT)/include/makeinclude/rules.bin.GNU -include $(ACE_ROOT)/include/makeinclude/rules.local.GNU - -#---------------------------------------------------------------------------- -# Local targets -#---------------------------------------------------------------------------- - -HTML : # - perl ../combine *.html - -rename : # - for i in *.cxx ; do \ - n=`expr "$$i" : "\(.*\).cxx"` ;\ - mv $$i $$n.cpp ;\ - done - -Indent : # - for i in $(SRC) $(HDR) ; do \ - indent -npsl -l80 -fca -fc1 -cli0 -cdb -ts2 -bl -bli0 < $$i | \ - sed -e 's/: :/::/g' \ - -e 's/^.*\(public:\)/\1/' \ - -e 's/^.*\(protected:\)/\1/' \ - -e 's/^.*\(private:\)/\1/' \ - -e 's/:\(public\)/ : \1/' \ - -e 's/:\(protected\)/ : \1/' \ - -e 's/:\(private\)/ : \1/' \ - -e 's/ / /g' \ - > $$i~ ;\ - mv $$i~ $$i ;\ - done - -Depend : depend - perl ../fix.Makefile -f $(MAKEFILE) -o $(DEPEND) - -$(DEPEND) : - touch $(DEPEND) - -#---------------------------------------------------------------------------- -# Dependencies -#---------------------------------------------------------------------------- - -include $(DEPEND) -include .depend.client diff --git a/docs/tutorials/015/Makefile.server b/docs/tutorials/015/Makefile.server deleted file mode 100644 index 109cecc8e90..00000000000 --- a/docs/tutorials/015/Makefile.server +++ /dev/null @@ -1,81 +0,0 @@ - -# $Id$ - -#---------------------------------------------------------------------------- -# Local macros -#---------------------------------------------------------------------------- - -BIN = server - -FILES += Protocol_Stream -FILES += Protocol_Task -FILES += Xmit -FILES += Recv -FILES += Compressor -FILES += Crypt - -FILES += Handler -FILES += Server_i - -BUILD = $(VBIN) - -SRC = $(addsuffix .cpp,$(BIN)) -SRC += $(addsuffix .cpp,$(FILES)) - -HDR = *.h - -MAKEFILE = Makefile.server -DEPEND = .depend.server - -#---------------------------------------------------------------------------- -# 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.lib.GNU -include $(ACE_ROOT)/include/makeinclude/rules.bin.GNU -include $(ACE_ROOT)/include/makeinclude/rules.local.GNU - -#---------------------------------------------------------------------------- -# Local targets -#---------------------------------------------------------------------------- - -HTML : # - perl ../combine *.html - -rename : # - for i in *.cxx ; do \ - n=`expr "$$i" : "\(.*\).cxx"` ;\ - mv $$i $$n.cpp ;\ - done - -Indent : # - for i in $(SRC) $(HDR) ; do \ - indent -npsl -l80 -fca -fc1 -cli0 -cdb -ts2 -bl -bli0 < $$i | \ - sed -e 's/: :/::/g' \ - -e 's/^.*\(public:\)/\1/' \ - -e 's/^.*\(protected:\)/\1/' \ - -e 's/^.*\(private:\)/\1/' \ - -e 's/:\(public\)/ : \1/' \ - -e 's/:\(protected\)/ : \1/' \ - -e 's/:\(private\)/ : \1/' \ - -e 's/ / /g' \ - > $$i~ ;\ - mv $$i~ $$i ;\ - done - -Depend : depend - perl ../fix.Makefile -f $(MAKEFILE) -o $(DEPEND) - -$(DEPEND) : - touch $(DEPEND) - -#---------------------------------------------------------------------------- -# Dependencies -#---------------------------------------------------------------------------- - -include $(DEPEND) -include .depend.server diff --git a/docs/tutorials/015/Protocol_Stream.cpp b/docs/tutorials/015/Protocol_Stream.cpp deleted file mode 100644 index ed9b866a1bd..00000000000 --- a/docs/tutorials/015/Protocol_Stream.cpp +++ /dev/null @@ -1,195 +0,0 @@ -// $Id$ - -#include "Protocol_Stream.h" -#include "Protocol_Task.h" - -#include "Xmit.h" -#include "Recv.h" - -#include "Compressor.h" -#include "Crypt.h" - -#include "ace/Stream_Modules.h" - -/* You can choose at compile time to include/exclude the protocol - pieces. -*/ -#define ENABLE_COMPRESSION -#define ENABLE_ENCRYPTION - -// The usual typedefs to make things easier to type. -typedef ACE_Module<ACE_MT_SYNCH> Module; -typedef ACE_Thru_Task<ACE_MT_SYNCH> Thru_Task; - -/* An ACE_Stream is a collection of ACE_Modules. You can think of it - as a doubly-linked list if you like. Each Module contains two - ACE_Task derivatives. One of these tasks is used when sending data - "upstream", the other is used for "downstream" operation. In some - cases, you'll only need to move data in one direction. To provide - a placeholder for the other direction, ACE_Thru_Task can be used. - ACE_Thru_Task responds to the put() by simply invoking put_next() - to send the data to the next module. - */ - -/* Do-nothing constructor and destructor - */ - -Protocol_Stream::Protocol_Stream (void) -{ -} - -Protocol_Stream::~Protocol_Stream (void) -{ -} - -/* Even opening the stream is rather simple. The important thing to - remember is that the modules you push onto the stream first will be - at the tail (eg -- most downstream) end of things when you're - done. - */ -int -Protocol_Stream::open (ACE_SOCK_Stream &peer, - Protocol_Task *reader) -{ - // Initialize our peer() to read/write the socket we're given - peer_.set_handle (peer.get_handle ()); - - // Construct (and remember) the Recv object so that we can read from - // the peer(). - ACE_NEW_RETURN (recv_, - Recv ( this->peer ()), - -1); - - // Add the transmit and receive tasks to the head of the stream. As - // we add more modules these will get pushed downstream and end up - // nearest the tail by the time we're done. - if (stream ().push (new Module ("Xmit/Recv", - new Xmit ( this->peer ()), - recv_)) == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "%p\n", - "stream().push(xmit/recv)"), - -1); - - // Add any other protocol tasks to the stream. Each one is added at - // the head. The net result is that Xmit/Recv are at the tail. - if (this->open () == -1) - return -1; - - // If a reader task was provided then push that in as the upstream - // side of the next-to-head module. Any data read from the peer() - // will be sent through here last. Server applications will - // typically use this task to do the actual processing of data. - // Note the use of Thru_Task. Since a module must always have a - // pair of tasks we use this on the writer side as a no-op. - if (reader) - { - if (stream ().push (new Module ("Reader", - new Thru_Task (), - reader)) == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "%p\n", - "stream().push(reader)"), - -1); - } - - return 0; -} - -/* Add the necessary protocol objects to the stream. The way we're - pushing things on we will encrypt the data before compressing it. -*/ -int -Protocol_Stream::open (void) -{ -#if defined (ENABLE_COMPRESSION) - if (stream ().push (new Module ("compress", - new Compressor (), - new Compressor ())) == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "%p\n", - "stream().push(comprssor)"), - -1); -#endif /* ENABLE_COMPRESSION */ - -#if defined (ENABLE_ENCRYPTION) - if (stream ().push (new Module ("crypt", - new Crypt (), - new Crypt ())) == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "%p\n", - "stream().push(crypt)"), - -1); -#endif /* ENABLE_ENCRYPTION */ - return 0; -} - -// Closing the Protocol_Stream is as simple as closing the ACE_Stream. -int -Protocol_Stream::close (void) -{ - return stream ().close (); -} - -// Simply pass the data directly to the ACE_Stream. -int -Protocol_Stream::put (ACE_Message_Block *&message, - ACE_Time_Value *timeout) -{ - return stream ().put (message, - timeout); -} - -/* Tell the Recv module to read some data from the peer and pass it - upstream. Servers will typically use this method in a - handle_input() method to tell the stream to get a client's request. */ - -int -Protocol_Stream::get(void) -{ - // If there is no Recv module, we're in big trouble! - if (recv_ == 0) - ACE_ERROR_RETURN ((LM_ERROR, - "(%P|%t) No Recv object!\n"), - -1); - - // This tells the Recv module to go to it's peer() and read some - // data. Once read, that data will be pushed upstream. If there is - // a reader object then it will have a chance to process the data. - // If not, the received data will be available in the message queue - // of the stream head's reader object (eg -- - // stream().head()->reader()->msg_queue()) and can be read with our - // other get() method below. - if (recv_->get () == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "(%P|%t) Cannot queue read request\n"), - -1); - - // For flexibility I've added an error() method to tell us if - // something bad has happened to the Recv object. - if (recv_->error ()) - ACE_ERROR_RETURN ((LM_ERROR, - "(%P|%t) Recv object error!\n"), - -1); - - return 0; -} - -/* Take a message block off of the stream head reader's message queue. - If the queue is empty, use get() to read from the peer. This is - most often used by client applications. Servers will generaly - insert a reader that will prevent the data from getting all the way - upstream to the head. */ -int -Protocol_Stream::get (ACE_Message_Block *&response, - ACE_Time_Value *timeout ) -{ - if (stream ().head ()->reader ()->msg_queue ()->is_empty () - && this->get () == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "(%P|%t) Cannot get data into the stream.\n"), - -1); - - return stream ().head ()->reader ()->getq (response, - timeout); -} diff --git a/docs/tutorials/015/Protocol_Stream.h b/docs/tutorials/015/Protocol_Stream.h deleted file mode 100644 index 7ff96f468fc..00000000000 --- a/docs/tutorials/015/Protocol_Stream.h +++ /dev/null @@ -1,86 +0,0 @@ -// $Id$ - -#ifndef PROTOCOL_STREAM_H -#define PROTOCOL_STREAM_H - -#include "ace/SOCK_Stream.h" - -#if !defined (ACE_LACKS_PRAGMA_ONCE) -# pragma once -#endif /* ACE_LACKS_PRAGMA_ONCE */ - -#include "ace/Stream.h" - -// Shorthand for the stream. -typedef ACE_Stream<ACE_MT_SYNCH> Stream; - -// Forward references to cut down on the number of #includes -class ACE_Message_Block; -class Recv; -class Protocol_Task; - -/* The Protocol_Stream provides a tidy interface to an ACE_Stream - setup to process a data block through a series of protocol stages. -*/ -class Protocol_Stream -{ -public: - Protocol_Stream (void); - ~Protocol_Stream (void); - - // Provide the stream with an ACE_SOCK_Stream on which it can - // communicate. If _reader is non-null, it will be added as the - // reader task just below the stream head so that it can process - // data read from the peer. - int open (ACE_SOCK_Stream &peer, - Protocol_Task *reader = 0); - - // Close the stream. All of the tasks & modules will also be - // closed. - int close (void); - - // putting data onto the stream will pass it through all protocol - // levels and send it to the peer. - int put (ACE_Message_Block *&message, - ACE_Time_Value *timeout = 0); - - // get will cause the Recv task (at the tail of the stream) to read - // some data from the peer and pass it upstream. The message block - // is then taken from the stream reader task's message queue. - int get (ACE_Message_Block *&response, - ACE_Time_Value *timeout = 0); - - // Tell the Recv task to read some data and send it upstream. The - // data will pass through the protocol tasks and be queued into the - // stream head reader task's message queue. If you've installed a - // _reader in open() then that task's recv() method will see the - // message and may consume it instead of passing it to the stream - // head for queueing. - int get (void); - - ACE_SOCK_Stream &peer (void) - { - return this->peer_; - } - -private: - // Our peer connection - ACE_SOCK_Stream peer_; - - // The stream managing the various protocol tasks - Stream stream_; - - // A task which is capable of receiving data on a socket. - // Note that this is only useful by client-side applications. - Recv *recv_; - - Stream &stream (void) - { - return this->stream_; - } - - // Install the protocol tasks into the stream. - int open (void); -}; - -#endif /* PROTOCOL_STREAM_H */ diff --git a/docs/tutorials/015/Protocol_Task.cpp b/docs/tutorials/015/Protocol_Task.cpp deleted file mode 100644 index b1eb82a43ad..00000000000 --- a/docs/tutorials/015/Protocol_Task.cpp +++ /dev/null @@ -1,73 +0,0 @@ - -// $Id$ - -#include "Protocol_Task.h" - -// Construct the object and remember the thread count. -Protocol_Task::Protocol_Task(void) -{ - ; -} - -Protocol_Task::~Protocol_Task(void) -{ - ; -} - -int Protocol_Task::open(void *arg) -{ - ACE_UNUSED_ARG(arg); - - return(0); -} - -int Protocol_Task::close(u_long flags) -{ - return 0; -} - -/* When a message is put() onto the task, it's time to process() some data. -*/ -int Protocol_Task::put(ACE_Message_Block *message,ACE_Time_Value *timeout) -{ - return this->process(message,timeout); -} - -/* Return an error since we don't want the task to ever be activated. - */ -int Protocol_Task::svc(void) -{ - return -1; -} - -/* There's nothing really magic about process(). We just decide if - we're moving data upstream or downstream and invoke the appropriate - virtual function to handle it. -*/ -int Protocol_Task::process(ACE_Message_Block * message, ACE_Time_Value *timeout) -{ - if( this->is_writer() ) - { - return this->send(message,timeout); - } - - return this->recv(message,timeout); -} - -/* We must insist that derivatives provide a meaningful overload for - these methods. It's fairly common for ACE object methods to return - an error when an overload is expected but the method cannot be - safely made pure virtual. - */ - -int Protocol_Task::send(ACE_Message_Block *message, - ACE_Time_Value *timeout) -{ - return -1; -} - -int Protocol_Task::recv(ACE_Message_Block * message, - ACE_Time_Value *timeout) -{ - return -1; -} diff --git a/docs/tutorials/015/Protocol_Task.h b/docs/tutorials/015/Protocol_Task.h deleted file mode 100644 index f886001678f..00000000000 --- a/docs/tutorials/015/Protocol_Task.h +++ /dev/null @@ -1,60 +0,0 @@ -// $Id$ - -#ifndef PROTOCOL_TASK_H -#define PROTOCOL_TASK_H - -#include "ace/Task.h" - -#if !defined (ACE_LACKS_PRAGMA_ONCE) -# pragma once -#endif /* ACE_LACKS_PRAGMA_ONCE */ - -/* A typical ACE_Task<> derivative that adds a few things appropriate - to protocol stacks. To keep things a little simpler, we prevent - activation of the task and just borrow the thread of control from - the calling method in all cases. -*/ -class Protocol_Task : public ACE_Task<ACE_MT_SYNCH> -{ -public: - typedef ACE_Task<ACE_MT_SYNCH> inherited; - - Protocol_Task (void); - - ~Protocol_Task (void); - - // open() is invoked when the task is inserted into the stream. - virtual int open (void *arg); - - // close() is invoked when the stream is closed (flags will be set - // to '1') and when the svc() method exits (flags will be '0'). - virtual int close (u_long flags); - - // As data travels through the stream, the put() method of each task - // is invoked to keep the data moving along. - virtual int put (ACE_Message_Block *message, - ACE_Time_Value *timeout); - - // We're obligated to provide this signature even though we won't be - // allowing this object to be activated. - virtual int svc (void); - -protected: - - // Called by put() or svc() as necessary to process a block of data. - int process (ACE_Message_Block *message, - ACE_Time_Value *timeout); - - // Tasks on the writer (downstream) side of the stream are called - // upon to send() data that will ultimately go to the peer. - virtual int send (ACE_Message_Block *message, - ACE_Time_Value *timeout); - - // Tasks on the reader (upstream) side will be receiving data that - // came from the peer. - virtual int recv (ACE_Message_Block *message, - ACE_Time_Value *timeout); - -}; - -#endif /* PROTOCOL_TASK_H */ diff --git a/docs/tutorials/015/Recv.cpp b/docs/tutorials/015/Recv.cpp deleted file mode 100644 index 121e50c213b..00000000000 --- a/docs/tutorials/015/Recv.cpp +++ /dev/null @@ -1,93 +0,0 @@ - -// $Id$ - -#include "Recv.h" -#include "ace/SOCK_Stream.h" - -/* Construct the object with the peer reference and other appropriate - initializations. -*/ -Recv::Recv( ACE_SOCK_Stream & _peer ) - : Protocol_Task(), peer_(_peer), error_(0) -{ - // Create the tickler that get() will use to trigger recv() - // through the baseclass. Since we're single-threaded this is - // probably overkill but it makes multi-threading easier if we - // choose to do that. - tickler_ = new ACE_Message_Block(1); -} - -/* Be sure we manage the lifetime of the tickler to prevent a memory - leak. -*/ -Recv::~Recv(void) -{ - tickler_->release(); -} - -/* By putting the tickler to ourselves we cause things to happen in - the baseclass that will invoke recv(). If we know we're single - threaded we could directly call recv() and be done with it but then - we'd have to do something else if we're multi-threaded. Just let - the baseclass worry about those things! -*/ -int Recv::get(void) -{ - return this->put( tickler_, 0 ); -} - -int Recv::recv(ACE_Message_Block * message, ACE_Time_Value *timeout) -{ - int rval; - - /* Xmit will send us the message length in clear-text. I - assume that will be less than 32-bytes! - */ - char msize[32]; - int b = 0; - - /* Read from the socket one byte at a time until we see then - end-of-string NULL character. Since the OS layers (at least - in Unix) will provide some buffering this isn't as bad as - it may seem at first. - - The byte-at-a-time recv breaks horribly on Win32 where the - WFMO_Reactor is used. This is because the socket has been - placed into non-blocking mode and only the recv() of the - first byte will block. The solution is to use - ACE_Select_Reactor which doesn't change the socket - characteristics. We did that back in main(), so we should - be in good shape now. - */ - do - { - rval = this->peer().recv( &msize[b], 1, timeout ); - if( rval == -1 ) - { - error_ = 1; - ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "Recv::recv() Failed to get message size."), -1); - } - } - while( msize[b++] != 0 ); - - int size = ACE_OS::atoi(msize); - - // Make a block big enough to contain the data we'll read - message = new ACE_Message_Block( size ); - - // Read the actual message data into our new message block - rval = this->peer().recv_n( message->wr_ptr(), size, 0, timeout ); - - // If we got the data correctly then send it on upstream. - if( rval > 0 ) - { - message->wr_ptr( rval ); - return( this->put_next( message ) ); - } - - // Something bad happend on the recv_n(). Set an error flag - // and return error. - error_ = 1; - - return( -1 ); -} diff --git a/docs/tutorials/015/Recv.h b/docs/tutorials/015/Recv.h deleted file mode 100644 index 3e65b3ecb1e..00000000000 --- a/docs/tutorials/015/Recv.h +++ /dev/null @@ -1,58 +0,0 @@ -// $Id$ - -#ifndef RECV_H -#define RECV_h - -#include "Protocol_Task.h" - -class ACE_SOCK_Stream; - -/* Get some data from the peer and send it upstream for - de-protocol-ization. -*/ -class Recv : public Protocol_Task -{ -public: - typedef Protocol_Task inherited; - - // Give it someone to talk to... - Recv (ACE_SOCK_Stream &peer); - ~Recv (void); - - // Trigger a read from the socket - int get (void); - - // In some cases it might be easier to check the "state" of the Recv - // object than to rely on return codes filtering back to you. - int error (void) - { - return this->error_; - } - -protected: - - ACE_SOCK_Stream &peer (void) - { - return this->peer_; - } - - // The baseclass will trigger this when our get() method is called. - // A message block of the appropriate size is created, filled and - // passed up the stream. - int recv (ACE_Message_Block *message, - ACE_Time_Value *timeout = 0); - -private: - // Our endpoint - ACE_SOCK_Stream &peer_; - - // get() uses a bogus message block to cause the baseclass to invoke - // recv(). To avoid memory thrashing, we create that bogus message - // once and reuse it for the life of Recv. - ACE_Message_Block *tickler_; - - // Our error flag (duh) - int error_; -}; - -#endif /* RECV_H */ diff --git a/docs/tutorials/015/Server_i.cpp b/docs/tutorials/015/Server_i.cpp deleted file mode 100644 index e71803b3d26..00000000000 --- a/docs/tutorials/015/Server_i.cpp +++ /dev/null @@ -1,75 +0,0 @@ - -// $Id$ - -#include "Server_i.h" - -/* We have to allocate space for our static finished_ flag. We also - initialize it to 'false' so that we don't exit immediately. -*/ -sig_atomic_t Server::finished_ = 0; - -/* The simple constructor and destructor don't do anything but give us - a place to expand in the future if we want. -*/ -Server::Server(void) -{ - ; -} - -Server::~Server(void) -{ - ; -} - -/* Opening the server is as simple as opening the acceptor with the - default ACE_Reactor instance. If we want to allow multiple - instances of Server objects then we should have an ACE_Reactor - member variable that we can register with. -*/ -int Server::open(void) -{ - if (acceptor_.open (ACE_INET_Addr (ACE_DEFAULT_SERVER_PORT), ACE_Reactor::instance()) == -1) - ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "open"), -1); - - return(0); -} - -/* Running the server just means that we execute the basic event - loop for the reactor. Again, if we had a private reactor then we - could have multiple server's in their run() method. -*/ -int Server::run(void) -{ - ACE_DEBUG ((LM_DEBUG, "(%P|%t) starting up server daemon\n")); - - // Here's the basic event loop. I have a 2-second timeout on - // the handle_events() so that we don't have to wait too long - // when we set the finished_ flag. - while (!finished_) - { - // Some (all?) platforms return the "remaining time" in the - // timeout parameter. If we don't reset it each time, we - // will end up with a 100% CPU spin loop! - ACE_Time_Value timeout(2); - - ACE_Reactor::instance()->handle_events (&timeout); - } - - // Close the acceptor when we're done. This may be handled by - // the framework but it's good practice to be explicit about things. - acceptor_.close(); - - ACE_DEBUG ((LM_DEBUG, "(%P|%t) shutting down server daemon\n")); - - return 0; -} - -/* The close() method simply sets the finished_ flag so that run() - will leave the event loop and exit. -*/ -int Server::close(void) -{ - finished_ = 1; - ACE_Reactor::instance()->notify(); - return(0); -} diff --git a/docs/tutorials/015/Server_i.h b/docs/tutorials/015/Server_i.h deleted file mode 100644 index 2a77c611565..00000000000 --- a/docs/tutorials/015/Server_i.h +++ /dev/null @@ -1,50 +0,0 @@ -// $Id$ - -#ifndef SERVER_H -#define SERVER_H - -#include "ace/Acceptor.h" - -#if !defined (ACE_LACKS_PRAGMA_ONCE) -# pragma once -#endif /* ACE_LACKS_PRAGMA_ONCE */ - -#include "ace/SOCK_Acceptor.h" -#include "Handler.h" - -/* Anytime I have templates I try to remember to create a typedef for - the parameterized object. It makes for much less typing later! -*/ -typedef ACE_Acceptor <Handler, ACE_SOCK_ACCEPTOR> Acceptor; - -class Server -{ -public: - // Our simple constructor takes no parameters. To make the - // server a bit more useful, you may want to pass in the - // TCP/IP port to be used by the acceptor. - Server (void); - ~Server (void); - - // Open the server for business - int open (void); - - // Close all server instances by setting the finished_ flag. - // Actually, the way this class is written, you can only have - // one instance. - static int close (void); - - // Run the server's main loop. The use of the gloabl ACE_Reactor by - // this method is what limits us to one Server instance. - int run (void); - -private: - // This will accept client connection requests and instantiate a - // Handler object for each new connection. - Acceptor acceptor_; - - // Our shutdown flag - static sig_atomic_t finished_; -}; - -#endif /* SERVER_H */ diff --git a/docs/tutorials/015/Xmit.cpp b/docs/tutorials/015/Xmit.cpp deleted file mode 100644 index 9450fc00cf0..00000000000 --- a/docs/tutorials/015/Xmit.cpp +++ /dev/null @@ -1,84 +0,0 @@ - -// $Id$ - -#include "Xmit.h" -#include "ace/SOCK_Stream.h" - -/* Construct the object with the peer connection and choose not to - activate ourselves into a dedicated thread. You might get some - performance gain by activating but if you really want a - multi-threaded apprroach you should handle that as a separate - issue. Attempting to force threading at this level will likely - cause more trouble than you want to deal with. -*/ -Xmit::Xmit( ACE_SOCK_Stream & _peer ) - : Protocol_Task(), peer_(_peer) -{ -} - -Xmit::~Xmit(void) -{ -} - -/* Check to see if we're being closed by the stream (flags != 0) or if - we're responding to the exit of our svc() method. -*/ -int Xmit::close(u_long flags) -{ - // Take care of the baseclass closure. - int rval = inherited::close(flags); - - // Only if we're being called at the stream shutdown do we close - // the peer connection. If, for some reason, we were activated - // into one or more threads we wouldn't want to close the pipe - // before all threads had a chance to flush their data. - if( flags ) - { - peer().close(); - } - - return( rval ); -} - -/* Our overload of send() will take care of sending the data to the - peer. -*/ -int Xmit::send(ACE_Message_Block *message, ACE_Time_Value *timeout) -{ - int rval; - - ACE_DEBUG ((LM_INFO, "(%P|%t) Xmit::send() sending (%s)(%d)\n", message->rd_ptr(), message->length() )); - - /* Since we're going to be sending data that may have been - compressed and encrypted it's probably important for the - receiver to get an entire "block" instead of having a - partial read. - - For that reason, we'll send the length of the message block - (in clear-text) to the peer so that it can then recv_n() - the entire block contents in one read operation. - */ - char msize[32]; - sprintf(msize,"%d",message->length()); - - // Be sure we send the end-of-string NULL so that Recv will - // know when to stop assembling the length. - rval = this->peer().send_n( msize, strlen(msize)+1, 0, timeout ); - - if( rval == -1 ) - { - ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "Xmit::send() Failed to send message size."), -1); - } - - /* Now we send the actual data. If you're worried about - network efficiency then you may choose to create one buffer - containing msize and the message data and send it all at - once. - */ - rval = this->peer().send_n( message->rd_ptr(), message->length(), 0, timeout ); - - // Release the message block since we're done with it. - message->release(); - - return( rval ); -} diff --git a/docs/tutorials/015/Xmit.h b/docs/tutorials/015/Xmit.h deleted file mode 100644 index 356bacf25b9..00000000000 --- a/docs/tutorials/015/Xmit.h +++ /dev/null @@ -1,46 +0,0 @@ -// $Id$ - -#ifndef XMIT_H -#define XMIT_h - -#include "Protocol_Task.h" - -// Forward reference reduces #include dependencies -class ACE_SOCK_Stream; - -/* A class suitable for sending data to a peer from within an - ACE_Stream. - */ -class Xmit : public Protocol_Task -{ -public: - typedef Protocol_Task inherited; - - // We must be given a valid peer when constructed. Without that we - // don't know who to send data to. - Xmit (ACE_SOCK_Stream &peer); - ~Xmit (void); - - // As you know, close() will be called in a couple of ways by the - // ACE framework. We use that opportunity to terminate the - // connection to the peer. - int close (u_long flags); - -protected: - - ACE_SOCK_Stream &peer (void) - { - return this->peer_; - } - - // Send the data to the peer. By now it will have been completely - // protocol-ized by other tasks in the stream. - int send (ACE_Message_Block *message, - ACE_Time_Value *timeout); - -private: - // A representation of the peer we're talking to. - ACE_SOCK_Stream &peer_; -}; - -#endif /* XMIT_H */ diff --git a/docs/tutorials/015/client.cpp b/docs/tutorials/015/client.cpp deleted file mode 100644 index a573b4f3902..00000000000 --- a/docs/tutorials/015/client.cpp +++ /dev/null @@ -1,70 +0,0 @@ - -// $Id$ - -/* The Client object will implement the nasty details of connecting to - communicating with the server -*/ -#include "Client_i.h" - -int main(int argc, char *argv[]) -{ - // How many messages will we send? - int mcount = argc > 1 ? ACE_OS::atoi(argv[1]) : 3; - - // Construct a Client with our desired endpoint. - Client client(ACE_DEFAULT_SERVER_PORT,ACE_DEFAULT_SERVER_HOST); - - // Attempt to open the connection to the server. - if( client.open() == -1 ) - { - ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "Client::open()"), -1); - } - - // Send a few messages to the server and get some responses... - for( int i = 0 ; i < mcount ; ++i ) - { - // Since we'll be using a Protocol Stream (even though we - // don't know that at this level) we require the use of - // ACE_Message_Block objects to send/receive data. - ACE_Message_Block * message = new ACE_Message_Block( 128 ); - - // Construct a silly message to send to the server. - // Notice that we're careful to add one to the strlen() so - // that we also send the end-of-string NULL character. - ACE_OS::sprintf (message->wr_ptr (), "This is message %d.", i); - message->wr_ptr (strlen (message->rd_ptr ())+1); - - // client will take ownership of the message block so that - // we don't have to remember to release(). We *do* have - // to remember not to use it after put() since it may be - // released almost immediately. - client.put( message ); - - ACE_Message_Block * response; - - // get() takes an ACE_Message_Block pointer reference. We then - // assume ownership of it and must release() when we're done. - if( client.get( response ) == -1 ) - { - ACE_DEBUG ((LM_INFO, "(%P|%t) Failed to get response from server\n" )); - break; - } - - ACE_DEBUG ((LM_INFO, "(%P|%t) The server's response: (%s)\n", - response->rd_ptr())); - - // Now that we're through with the response we have to - // release() it to avoid memory leaks. - response->release(); - } - - ACE_DEBUG ((LM_INFO, "(%P|%t) Shutting down the stream\n" )); - - // Before we exit, it's a good idea to properly close() the connection. - if( client.close() == -1 ) - { - ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "Client::close()"), -1); - } - - return(0); -} diff --git a/docs/tutorials/015/combine.shar b/docs/tutorials/015/combine.shar deleted file mode 100644 index 68a509ce351..00000000000 --- a/docs/tutorials/015/combine.shar +++ /dev/null @@ -1,1063 +0,0 @@ -#!/bin/sh -# This is a shell archive (produced by GNU sharutils 4.2). -# To extract the files from this archive, save it to some FILE, remove -# everything before the `!/bin/sh' line above, then type `sh FILE'. -# -# Made on 1999-02-14 13:38 EST by <jcej@chiroptera.tragus.org>. -# Source directory was `/var/home/jcej/projects/ACE_wrappers/docs/tutorials/015'. -# -# Existing files will *not* be overwritten unless `-c' is specified. -# -# This shar contains: -# length mode name -# ------ ---------- ------------------------------------------ -# 414 -rw-rw-r-- hdr -# 419 -rw-rw-r-- bodies -# 4228 -rw-rw-r-- page01.pre -# 194 -rw-rw-r-- page02.pre -# 318 -rw-rw-r-- page03.pre -# 178 -rw-rw-r-- page04.pre -# 304 -rw-rw-r-- page05.pre -# 418 -rw-rw-r-- page06.pre -# 321 -rw-rw-r-- page07.pre -# 501 -rw-rw-r-- page08.pre -# 640 -rw-rw-r-- page09.pre -# 978 -rw-rw-r-- page10.pre -# 334 -rw-rw-r-- page11.pre -# 49 -rw-rw-r-- page12.pre -# 326 -rw-rw-r-- page13.pre -# 540 -rw-rw-r-- page14.pre -# 770 -rw-rw-r-- page15.pre -# 660 -rw-rw-r-- page16.pre -# 213 -rw-rw-r-- page17.pre -# 372 -rw-rw-r-- page18.pre -# 281 -rw-rw-r-- page19.pre -# 356 -rw-rw-r-- page20.pre -# 151 -rw-rw-r-- page21.pre -# 2567 -rw-rw-r-- page22.pre -# 406 -rw-rw-r-- page04.pst -# 617 -rw-rw-r-- page09.pst -# -save_IFS="${IFS}" -IFS="${IFS}:" -gettext_dir=FAILED -locale_dir=FAILED -first_param="$1" -for dir in $PATH -do - if test "$gettext_dir" = FAILED && test -f $dir/gettext \ - && ($dir/gettext --version >/dev/null 2>&1) - then - set `$dir/gettext --version 2>&1` - if test "$3" = GNU - then - gettext_dir=$dir - fi - fi - if test "$locale_dir" = FAILED && test -f $dir/shar \ - && ($dir/shar --print-text-domain-dir >/dev/null 2>&1) - then - locale_dir=`$dir/shar --print-text-domain-dir` - fi -done -IFS="$save_IFS" -if test "$locale_dir" = FAILED || test "$gettext_dir" = FAILED -then - echo=echo -else - TEXTDOMAINDIR=$locale_dir - export TEXTDOMAINDIR - TEXTDOMAIN=sharutils - export TEXTDOMAIN - echo="$gettext_dir/gettext -s" -fi -touch -am 1231235999 $$.touch >/dev/null 2>&1 -if test ! -f 1231235999 && test -f $$.touch; then - shar_touch=touch -else - shar_touch=: - echo - $echo 'WARNING: not restoring timestamps. Consider getting and' - $echo "installing GNU \`touch', distributed in GNU File Utilities..." - echo -fi -rm -f 1231235999 $$.touch -# -if mkdir _sh31334; then - $echo 'x -' 'creating lock directory' -else - $echo 'failed to create lock directory' - exit 1 -fi -# ============= hdr ============== -if test -f 'hdr' && test "$first_param" != -c; then - $echo 'x -' SKIPPING 'hdr' '(file already exists)' -else - $echo 'x -' extracting 'hdr' '(text)' - sed 's/^X//' << 'SHAR_EOF' > 'hdr' && -<HTML> -<HEAD> -X <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> -X <META NAME="Author" CONTENT="James CE Johnson"> -X <TITLE>ACE Tutorial 015</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> -X -<CENTER><B><FONT SIZE=+2>ACE Tutorial 015</FONT></B></CENTER> -X -<CENTER><B><FONT SIZE=+2>Building a protocol stream</FONT></B></CENTER> -X -<P> -<HR WIDTH="100%"> -SHAR_EOF - $shar_touch -am 1019173798 'hdr' && - chmod 0664 'hdr' || - $echo 'restore of' 'hdr' 'failed' - if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \ - && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then - md5sum -c << SHAR_EOF >/dev/null 2>&1 \ - || $echo 'hdr:' 'MD5 check failed' -41322d388f7bb6c8eba031c4a6ab53ce hdr -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'hdr'`" - test 414 -eq "$shar_count" || - $echo 'hdr:' 'original size' '414,' 'current size' "$shar_count!" - fi -fi -# ============= bodies ============== -if test -f 'bodies' && test "$first_param" != -c; then - $echo 'x -' SKIPPING 'bodies' '(file already exists)' -else - $echo 'x -' extracting 'bodies' '(text)' - sed 's/^X//' << 'SHAR_EOF' > 'bodies' && -# -# The client application specific files -# -PAGE=2 -client.cpp -Client_i.h -Client_i.cpp -# -# The server application specific files -# -server.cpp -Server_i.h -Server_i.cpp -Handler.h -Handler.cpp -# -# The basic protocol stream -# -Protocol_Stream.h -Protocol_Stream.cpp -Protocol_Task.h -Protocol_Task.cpp -# -# Send/Receive objects -# -XXmit.h -XXmit.cpp -Recv.h -Recv.cpp -# -# Protocol objects -# -Compressor.h -Compressor.cpp -Crypt.h -Crypt.cpp -SHAR_EOF - $shar_touch -am 1022205498 'bodies' && - chmod 0664 'bodies' || - $echo 'restore of' 'bodies' 'failed' - if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \ - && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then - md5sum -c << SHAR_EOF >/dev/null 2>&1 \ - || $echo 'bodies:' 'MD5 check failed' -a6c99d6567b0640ad524b196dc43647e bodies -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'bodies'`" - test 419 -eq "$shar_count" || - $echo 'bodies:' 'original size' '419,' 'current size' "$shar_count!" - fi -fi -# ============= page01.pre ============== -if test -f 'page01.pre' && test "$first_param" != -c; then - $echo 'x -' SKIPPING 'page01.pre' '(file already exists)' -else - $echo 'x -' extracting 'page01.pre' '(text)' - sed 's/^X//' << 'SHAR_EOF' > 'page01.pre' && -X -In a typical client/server system you will be sending and receiving -X data. That's the whole point after all. -<P> -In the client/server tutorials that we've done so far it was just a -X matter of sending a buffer of data to the peer. This was done -X with the send*() and recv*() methods of the ACE_SOCK* objects. -<P> -In a more robust system, one might want to process the data before -X sending it to a peer and "unprocess" it after reading from a -X peer. These processing steps might include encryption, -X compression, applying checksums or any number of other actions. -<P> -In this tutorial a Protocol_Stream object is created to encrypt and -X compress* data being sent between peers. Both client and server -X applications are presented as well. I present the application -level code first and then go into the details of the protocol stream -and it's helper objects. If the stream stuff in the application logic -is confusing then just read on by and come back to it after the later -discussions. -<P> -Disclaimer: -<br> -<ul> -Several folks have reported problems with this tutorial on Win32. -There are a couple of ways to solve this. I've chosen to solve it by -using the ACE_Select_Reactor on all platforms instead of taking the -OS-default. -</ul> -<P> -Kirthika's abstract: -<UL> -The Protocol Stream model consists of a stream layer which pushes the -data towards the underlying SOCK_Stream thru the stages of encryption -and compression. This data is received at the other end of the -SOCK_Stream and sent up to its Protocol_Stream layer via the stages of -decompression and decryption and an optional Reader task. This is very -similar to the model of the TCP/IP stack (specifically the datalink to -physical layer portion). -<P> -ACE_Message_Blocks are used to communicate between the client and the -server across the Protocol Stream, which abstracts the protocol -conformance details. The underlying SOCK_Stream is used to set up the -connection using the ACE_SOCK_Connector class. Once the connector -completes its job, the SOCK_Stream pointer is passed on to the -Protocol Stream which now takes over. The Client has put() and get() -methods to send and receive data from the server. -<P> -The server is implemented using the ACE_Acceptor to listen at the port -for connections and a reactor for delegating events to the appropriate -event handler. The handle_input () method of the handler simply allows -the stream to receive the data and hand it over to the Handler_Task (a -derivative of the ACE_Task) which will then process it. -<P> -The implementation of this Protocol Stream model is done using the -ACE_Module class. The module for Xmit/Recv is shoved in first -into the stream, followed by the compression and encryption modules. The -optional Reader if defined is bundled with a dummy task -(ACE_Thru_Task class) into a module. The get() and put() methods do -the job of reading and writing to the Stream. Each module is made up -of a pair of Protocol Tasks. A Protocol Task is a derivative of the -ACE_Task and whose recv() and send() methods need to be filled to -perform the appropriate task. -<P> -The Xmit object derives from the Protocol task and has a send() method -which does the task of transmitting data to the underlying -SOCK_Stream. Keeping the fragmentation and reassembly issues in mind, -block-size is also sent across with the block of data. -The Recv object uses a dummy Message Block to provoke the Protocol -Task object to call the recv() on it. This is done by being -foresighted about the use of mutliple threads instead of a single -thread. -<P> -The compression/decompression is bundled in a single Protocol Task -object with the send () method doing the compression and the recv() -doing the decompression. Similarly, the encrption/decryption is done -using a single Protocol Task object. -<P> -This tutorial provides a glimpse on how to design and implement a -protocol in layers and also revises a lot of what has been learnt until -now from the previous tutorials. -(for instance, Message_Block, Task, Acceptor, Connector, Event_Handler -etc.) -</UL> -<P> -<font size=-1>* Ok, I didn't really implement encryption and -X compression objects. I'll leave that as a thought -X exercise!</font> -SHAR_EOF - $shar_touch -am 0214124599 'page01.pre' && - chmod 0664 'page01.pre' || - $echo 'restore of' 'page01.pre' 'failed' - if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \ - && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then - md5sum -c << SHAR_EOF >/dev/null 2>&1 \ - || $echo 'page01.pre:' 'MD5 check failed' -a09c3ff1f21a90aab991e0f38dc00458 page01.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page01.pre'`" - test 4228 -eq "$shar_count" || - $echo 'page01.pre:' 'original size' '4228,' 'current size' "$shar_count!" - fi -fi -# ============= page02.pre ============== -if test -f 'page02.pre' && test "$first_param" != -c; then - $echo 'x -' SKIPPING 'page02.pre' '(file already exists)' -else - $echo 'x -' extracting 'page02.pre' '(text)' - sed 's/^X//' << 'SHAR_EOF' > 'page02.pre' && -We'll take a look first at the client application. As usual, our goal -X is to keep the main() application as simple as possible and -X delegate the tricky stuff to another object. -X -<HR> -SHAR_EOF - $shar_touch -am 1019173798 'page02.pre' && - chmod 0664 'page02.pre' || - $echo 'restore of' 'page02.pre' 'failed' - if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \ - && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then - md5sum -c << SHAR_EOF >/dev/null 2>&1 \ - || $echo 'page02.pre:' 'MD5 check failed' -6a2e64962c95b349625f418502c95952 page02.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page02.pre'`" - test 194 -eq "$shar_count" || - $echo 'page02.pre:' 'original size' '194,' 'current size' "$shar_count!" - fi -fi -# ============= page03.pre ============== -if test -f 'page03.pre' && test "$first_param" != -c; then - $echo 'x -' SKIPPING 'page03.pre' '(file already exists)' -else - $echo 'x -' extracting 'page03.pre' '(text)' - sed 's/^X//' << 'SHAR_EOF' > 'page03.pre' && -The Client object is designed to hide all of the messy connection -X logic from it's users. It also provides put/get methods for -X sending data to the server and receiving the server's response. -X Note the Protocol_Stream member that will take care of -X converting and sending/receiving the data. -<HR> -SHAR_EOF - $shar_touch -am 1019173798 'page03.pre' && - chmod 0664 'page03.pre' || - $echo 'restore of' 'page03.pre' 'failed' - if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \ - && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then - md5sum -c << SHAR_EOF >/dev/null 2>&1 \ - || $echo 'page03.pre:' 'MD5 check failed' -95326c064b10bbda428d3c967f285760 page03.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page03.pre'`" - test 318 -eq "$shar_count" || - $echo 'page03.pre:' 'original size' '318,' 'current size' "$shar_count!" - fi -fi -# ============= page04.pre ============== -if test -f 'page04.pre' && test "$first_param" != -c; then - $echo 'x -' SKIPPING 'page04.pre' '(file already exists)' -else - $echo 'x -' extracting 'page04.pre' '(text)' - sed 's/^X//' << 'SHAR_EOF' > 'page04.pre' && -The implementation of the Client object. Only the open() method -X really does any work. The other methods simply delegate their -X function to the Protocol_Stream. -<HR> -SHAR_EOF - $shar_touch -am 1019173798 'page04.pre' && - chmod 0664 'page04.pre' || - $echo 'restore of' 'page04.pre' 'failed' - if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \ - && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then - md5sum -c << SHAR_EOF >/dev/null 2>&1 \ - || $echo 'page04.pre:' 'MD5 check failed' -2955ca8d3b0fc6840f3d371aea528b8d page04.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page04.pre'`" - test 178 -eq "$shar_count" || - $echo 'page04.pre:' 'original size' '178,' 'current size' "$shar_count!" - fi -fi -# ============= page05.pre ============== -if test -f 'page05.pre' && test "$first_param" != -c; then - $echo 'x -' SKIPPING 'page05.pre' '(file already exists)' -else - $echo 'x -' extracting 'page05.pre' '(text)' - sed 's/^X//' << 'SHAR_EOF' > 'page05.pre' && -Like the client, we want to keep the main() part of our server code as -X simple as possible. This is done by putting most of the work -X into the Handler object that will deal with client connections. -XFrom the looks of the code below, I think we've been successful in our -simplification. -<HR> -X -SHAR_EOF - $shar_touch -am 1019173798 'page05.pre' && - chmod 0664 'page05.pre' || - $echo 'restore of' 'page05.pre' 'failed' - if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \ - && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then - md5sum -c << SHAR_EOF >/dev/null 2>&1 \ - || $echo 'page05.pre:' 'MD5 check failed' -8833b0d7f90a4d13f68b8cdb9147c29a page05.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page05.pre'`" - test 304 -eq "$shar_count" || - $echo 'page05.pre:' 'original size' '304,' 'current size' "$shar_count!" - fi -fi -# ============= page06.pre ============== -if test -f 'page06.pre' && test "$first_param" != -c; then - $echo 'x -' SKIPPING 'page06.pre' '(file already exists)' -else - $echo 'x -' extracting 'page06.pre' '(text)' - sed 's/^X//' << 'SHAR_EOF' > 'page06.pre' && -The Server object exists in order simplify the -main() application level. To that end, it hides the details of -creating an acceptor and managing the reactor. -<P> -The static close() method available for a signal handler as you saw on -the previous page. Of course the assumption here is that there would -only be one Server instance but since you can't provide a TCP/IP port, -that's probably a valid assumption! -<HR> -SHAR_EOF - $shar_touch -am 1019173798 'page06.pre' && - chmod 0664 'page06.pre' || - $echo 'restore of' 'page06.pre' 'failed' - if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \ - && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then - md5sum -c << SHAR_EOF >/dev/null 2>&1 \ - || $echo 'page06.pre:' 'MD5 check failed' -06a0abefdf4e704b42147f433bd27e4d page06.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page06.pre'`" - test 418 -eq "$shar_count" || - $echo 'page06.pre:' 'original size' '418,' 'current size' "$shar_count!" - fi -fi -# ============= page07.pre ============== -if test -f 'page07.pre' && test "$first_param" != -c; then - $echo 'x -' SKIPPING 'page07.pre' '(file already exists)' -else - $echo 'x -' extracting 'page07.pre' '(text)' - sed 's/^X//' << 'SHAR_EOF' > 'page07.pre' && -And now the implementation of Server. This is actually just the -main() code from a previous tutorial broken into appropriate method -calls. It may seem silly to do this rather than keeping the stuff in -main() but you'll find that you have less trouble enhancing an -application when you take this sort of approach. -<HR> -X -SHAR_EOF - $shar_touch -am 1019173798 'page07.pre' && - chmod 0664 'page07.pre' || - $echo 'restore of' 'page07.pre' 'failed' - if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \ - && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then - md5sum -c << SHAR_EOF >/dev/null 2>&1 \ - || $echo 'page07.pre:' 'MD5 check failed' -7dfb75884939c3c05ee1e1000956e9f4 page07.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page07.pre'`" - test 321 -eq "$shar_count" || - $echo 'page07.pre:' 'original size' '321,' 'current size' "$shar_count!" - fi -fi -# ============= page08.pre ============== -if test -f 'page08.pre' && test "$first_param" != -c; then - $echo 'x -' SKIPPING 'page08.pre' '(file already exists)' -else - $echo 'x -' extracting 'page08.pre' '(text)' - sed 's/^X//' << 'SHAR_EOF' > 'page08.pre' && -The Handler object is our event handler. You can use either -ACE_Event_Handler or ACE_Svc_Handler<> for the baseclass. I generally -prefer the latter since it takes care of some housekeeping that I -would otherwise be responsible for. -<P> -The class declaration is taken almost exactly from a previous -tutorial. A good design will have a simple handler object that will -collect data from the peer and pass it along to another object for -processing. Again, keep it simple and delegate authority. -<HR> -SHAR_EOF - $shar_touch -am 1019173798 'page08.pre' && - chmod 0664 'page08.pre' || - $echo 'restore of' 'page08.pre' 'failed' - if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \ - && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then - md5sum -c << SHAR_EOF >/dev/null 2>&1 \ - || $echo 'page08.pre:' 'MD5 check failed' -471889eb736a025fc46719549bca160a page08.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page08.pre'`" - test 501 -eq "$shar_count" || - $echo 'page08.pre:' 'original size' '501,' 'current size' "$shar_count!" - fi -fi -# ============= page09.pre ============== -if test -f 'page09.pre' && test "$first_param" != -c; then - $echo 'x -' SKIPPING 'page09.pre' '(file already exists)' -else - $echo 'x -' extracting 'page09.pre' '(text)' - sed 's/^X//' << 'SHAR_EOF' > 'page09.pre' && -Like any other event handler, the handle_input() method will be -responsible for getting data from the peer() and doing something with -it. In this case, we have a Protocol_Stream to deal with. We'll use -the stream for the actual I/O but we are ultimately responsible for -processing the data from the peer. To do that, we've created a -Handler_Task that fits within the Protocol_Stream framework to process -data that has been received. Handler::handle_input() will tell the stream that -it's time to read data and that data will eventually show up at -Handler_Task::recv() where we'll process it as required by our -application logic. -<HR> -SHAR_EOF - $shar_touch -am 1019173798 'page09.pre' && - chmod 0664 'page09.pre' || - $echo 'restore of' 'page09.pre' 'failed' - if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \ - && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then - md5sum -c << SHAR_EOF >/dev/null 2>&1 \ - || $echo 'page09.pre:' 'MD5 check failed' -da5c4b11d356dc9caf3a8e3b6b2527a6 page09.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page09.pre'`" - test 640 -eq "$shar_count" || - $echo 'page09.pre:' 'original size' '640,' 'current size' "$shar_count!" - fi -fi -# ============= page10.pre ============== -if test -f 'page10.pre' && test "$first_param" != -c; then - $echo 'x -' SKIPPING 'page10.pre' '(file already exists)' -else - $echo 'x -' extracting 'page10.pre' '(text)' - sed 's/^X//' << 'SHAR_EOF' > 'page10.pre' && -And so finally we come to the Protocol_Stream. That, after all, is -the focus of the entire tutorial but it took us half of the day to get -here! -<P> -The Protocol_Stream uses an ACE_Stream to move an ACE_Message_Block -through a series of tasks. Each task in the stream is responsible for -performing some operation on the data in the message block. That is -the nature of a protocol stream (or "stack" if you prefer). In this -stream, the data is compressed and encrypted* on its way between -peers. We also allow users of the stream to install a reader task to -handle data that percolates up from the peer. As you saw a page or -two ago, this is most useful for a server. -X -<P> -<font size=-1>*Again, I just pretend to do these things. It would -take another day or two to go through any sort of reasonable -encryption or compression!</font> -<P> -Before we get into the code, here's a picture that's shows what's -going on here. -<P><center><img src="stream.gif"></center></p> -<HR> -SHAR_EOF - $shar_touch -am 1019173798 'page10.pre' && - chmod 0664 'page10.pre' || - $echo 'restore of' 'page10.pre' 'failed' - if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \ - && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then - md5sum -c << SHAR_EOF >/dev/null 2>&1 \ - || $echo 'page10.pre:' 'MD5 check failed' -a74423390fb5217104c6d89d7f202e8b page10.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page10.pre'`" - test 978 -eq "$shar_count" || - $echo 'page10.pre:' 'original size' '978,' 'current size' "$shar_count!" - fi -fi -# ============= page11.pre ============== -if test -f 'page11.pre' && test "$first_param" != -c; then - $echo 'x -' SKIPPING 'page11.pre' '(file already exists)' -else - $echo 'x -' extracting 'page11.pre' '(text)' - sed 's/^X//' << 'SHAR_EOF' > 'page11.pre' && -And now the implementation of the Protocol_Stream. There are more -lines of code here than we've seen so far but it still isn't -complicated. The basic idea is to construct the ACE_Stream with our -set of protocol objects that will manipulate the data. Our primary -concern in this file is to get everything in the correct order! -<HR> -SHAR_EOF - $shar_touch -am 1019173798 'page11.pre' && - chmod 0664 'page11.pre' || - $echo 'restore of' 'page11.pre' 'failed' - if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \ - && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then - md5sum -c << SHAR_EOF >/dev/null 2>&1 \ - || $echo 'page11.pre:' 'MD5 check failed' -b0e968102fb417b12710e99465f4e387 page11.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page11.pre'`" - test 334 -eq "$shar_count" || - $echo 'page11.pre:' 'original size' '334,' 'current size' "$shar_count!" - fi -fi -# ============= page12.pre ============== -if test -f 'page12.pre' && test "$first_param" != -c; then - $echo 'x -' SKIPPING 'page12.pre' '(file already exists)' -else - $echo 'x -' extracting 'page12.pre' '(text)' - sed 's/^X//' << 'SHAR_EOF' > 'page12.pre' && -A quick look at the Protocol_Task header... -<HR> -SHAR_EOF - $shar_touch -am 0210223499 'page12.pre' && - chmod 0664 'page12.pre' || - $echo 'restore of' 'page12.pre' 'failed' - if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \ - && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then - md5sum -c << SHAR_EOF >/dev/null 2>&1 \ - || $echo 'page12.pre:' 'MD5 check failed' -5258df32a7fddcecfe902aec8440f98f page12.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page12.pre'`" - test 49 -eq "$shar_count" || - $echo 'page12.pre:' 'original size' '49,' 'current size' "$shar_count!" - fi -fi -# ============= page13.pre ============== -if test -f 'page13.pre' && test "$first_param" != -c; then - $echo 'x -' SKIPPING 'page13.pre' '(file already exists)' -else - $echo 'x -' extracting 'page13.pre' '(text)' - sed 's/^X//' << 'SHAR_EOF' > 'page13.pre' && -The Protocol_Task implementation takes care of the open(), close(), -put() and svc() methods so that derivatives can concentrate on the -send() and recv() methods. After a while you find that most -ACE_Task<> derivatives look very similar in the four basic methods and -only need one or two additional to do any real work. -<HR> -SHAR_EOF - $shar_touch -am 1019173798 'page13.pre' && - chmod 0664 'page13.pre' || - $echo 'restore of' 'page13.pre' 'failed' - if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \ - && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then - md5sum -c << SHAR_EOF >/dev/null 2>&1 \ - || $echo 'page13.pre:' 'MD5 check failed' -8b74a6d79d158222928097a9bb1335db page13.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page13.pre'`" - test 326 -eq "$shar_count" || - $echo 'page13.pre:' 'original size' '326,' 'current size' "$shar_count!" - fi -fi -# ============= page14.pre ============== -if test -f 'page14.pre' && test "$first_param" != -c; then - $echo 'x -' SKIPPING 'page14.pre' '(file already exists)' -else - $echo 'x -' extracting 'page14.pre' '(text)' - sed 's/^X//' << 'SHAR_EOF' > 'page14.pre' && -The Xmit object knows how to send data to the peer. It sits at the -tail of the stream and gets everything that flows down from the head. -In keeping with the spirit of things, this object does only one thing -and doesn't concern itself with anyone else' details. -<P> -The only thing you might want to do is combine it with Recv. Why? -As you'll realize in a page or two, the Xmit and Recv objects must -interact if you're going to ensure a safe transit. By having a single -object it's easier to coordinate and maintain the interaction. -<HR> -SHAR_EOF - $shar_touch -am 1019213498 'page14.pre' && - chmod 0664 'page14.pre' || - $echo 'restore of' 'page14.pre' 'failed' - if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \ - && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then - md5sum -c << SHAR_EOF >/dev/null 2>&1 \ - || $echo 'page14.pre:' 'MD5 check failed' -bfc300ca2da5b82a5e452713cbf2f544 page14.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page14.pre'`" - test 540 -eq "$shar_count" || - $echo 'page14.pre:' 'original size' '540,' 'current size' "$shar_count!" - fi -fi -# ============= page15.pre ============== -if test -f 'page15.pre' && test "$first_param" != -c; then - $echo 'x -' SKIPPING 'page15.pre' '(file already exists)' -else - $echo 'x -' extracting 'page15.pre' '(text)' - sed 's/^X//' << 'SHAR_EOF' > 'page15.pre' && -The implementation of Xmit isn't too complicated. If we choose to -combine it with the Recv task we simply lift the recv() method from -that object and drop it into this one. -<P> -Note that close() must decide if it's being called when the stream is -shutdown or when it's svc() method exits. Since we tell the baseclass -not to use any threads it's a safe bet that flags will always be -non-zero. Still, it's good practice to plan for the future by -checking the value. -<P> -Note also that when we send the data we prefix it with the data size. -This let's our sibling Recv ensure that an entire block is received -together. This can be very important for compression and encryption -processes which typically work better with blocks of data instead of -streams of data. -<HR> -SHAR_EOF - $shar_touch -am 1019173798 'page15.pre' && - chmod 0664 'page15.pre' || - $echo 'restore of' 'page15.pre' 'failed' - if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \ - && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then - md5sum -c << SHAR_EOF >/dev/null 2>&1 \ - || $echo 'page15.pre:' 'MD5 check failed' -0d79137eaedd73b820037fcafe6e16b6 page15.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page15.pre'`" - test 770 -eq "$shar_count" || - $echo 'page15.pre:' 'original size' '770,' 'current size' "$shar_count!" - fi -fi -# ============= page16.pre ============== -if test -f 'page16.pre' && test "$first_param" != -c; then - $echo 'x -' SKIPPING 'page16.pre' '(file already exists)' -else - $echo 'x -' extracting 'page16.pre' '(text)' - sed 's/^X//' << 'SHAR_EOF' > 'page16.pre' && -Recv is the sibling to Xmit. Again, they could be combined into a -single object if you want. -<P> -An ACE_Stream is designed to handle downstream traffic very -well. You put() data into it and it flows along towards the tail. -However, there doesn't seem to be a way to put data in such that it -will travel upstream. To get around that, I've added a get() method -to Recv that will trigger a read on the socket. Recv will then put -the data to the next upstream module and we're on our way. As noted -earlier, that data will eventually show up either in the <i>reader</i> -(if installed on the stream open()) or the stream head reader task's -message queue. -<HR> -SHAR_EOF - $shar_touch -am 1019173798 'page16.pre' && - chmod 0664 'page16.pre' || - $echo 'restore of' 'page16.pre' 'failed' - if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \ - && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then - md5sum -c << SHAR_EOF >/dev/null 2>&1 \ - || $echo 'page16.pre:' 'MD5 check failed' -2d89b3c894cfcfdfef47ae506913cdad page16.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page16.pre'`" - test 660 -eq "$shar_count" || - $echo 'page16.pre:' 'original size' '660,' 'current size' "$shar_count!" - fi -fi -# ============= page17.pre ============== -if test -f 'page17.pre' && test "$first_param" != -c; then - $echo 'x -' SKIPPING 'page17.pre' '(file already exists)' -else - $echo 'x -' extracting 'page17.pre' '(text)' - sed 's/^X//' << 'SHAR_EOF' > 'page17.pre' && -The Recv implementation is nearly as simple as Xmit. There's -opportunity for error when we get the message size and we have to -manage the lifetime of the tickler but other than that it's pretty -basic stuff. -<HR> -SHAR_EOF - $shar_touch -am 1019173798 'page17.pre' && - chmod 0664 'page17.pre' || - $echo 'restore of' 'page17.pre' 'failed' - if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \ - && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then - md5sum -c << SHAR_EOF >/dev/null 2>&1 \ - || $echo 'page17.pre:' 'MD5 check failed' -7db337f2c6ec74d75560534dec550b0e page17.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page17.pre'`" - test 213 -eq "$shar_count" || - $echo 'page17.pre:' 'original size' '213,' 'current size' "$shar_count!" - fi -fi -# ============= page18.pre ============== -if test -f 'page18.pre' && test "$first_param" != -c; then - $echo 'x -' SKIPPING 'page18.pre' '(file already exists)' -else - $echo 'x -' extracting 'page18.pre' '(text)' - sed 's/^X//' << 'SHAR_EOF' > 'page18.pre' && -This and the next three pages present the protocol objects that -provide compression and encryption. If you were hoping to learn the -secrets of compression and encryption then I'm going to disappoint -you. There are some really good libraries out there that do this -stuff though and if anyone wants to integrate one of them into the -tutorial I'll be glad to take it! -<HR> -SHAR_EOF - $shar_touch -am 1019213698 'page18.pre' && - chmod 0664 'page18.pre' || - $echo 'restore of' 'page18.pre' 'failed' - if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \ - && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then - md5sum -c << SHAR_EOF >/dev/null 2>&1 \ - || $echo 'page18.pre:' 'MD5 check failed' -dc5f706bd5a27009aed167c0b137648e page18.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page18.pre'`" - test 372 -eq "$shar_count" || - $echo 'page18.pre:' 'original size' '372,' 'current size' "$shar_count!" - fi -fi -# ============= page19.pre ============== -if test -f 'page19.pre' && test "$first_param" != -c; then - $echo 'x -' SKIPPING 'page19.pre' '(file already exists)' -else - $echo 'x -' extracting 'page19.pre' '(text)' - sed 's/^X//' << 'SHAR_EOF' > 'page19.pre' && -Here we implement the details of our compression. By having both -compression and decompression in one object it's easier to keep track -of implementation details. Splitting Xmit/Recv like I did will make -things more difficult if something has to change in their interaction. -<HR> -SHAR_EOF - $shar_touch -am 1019205798 'page19.pre' && - chmod 0664 'page19.pre' || - $echo 'restore of' 'page19.pre' 'failed' - if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \ - && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then - md5sum -c << SHAR_EOF >/dev/null 2>&1 \ - || $echo 'page19.pre:' 'MD5 check failed' -4eb5dcd181f180d6c460971903efb288 page19.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page19.pre'`" - test 281 -eq "$shar_count" || - $echo 'page19.pre:' 'original size' '281,' 'current size' "$shar_count!" - fi -fi -# ============= page20.pre ============== -if test -f 'page20.pre' && test "$first_param" != -c; then - $echo 'x -' SKIPPING 'page20.pre' '(file already exists)' -else - $echo 'x -' extracting 'page20.pre' '(text)' - sed 's/^X//' << 'SHAR_EOF' > 'page20.pre' && -While I might be able to come up with a competitive compressor, I -don't have a snowball's chance to code up encryption. I'd be better -off piping the data through the standard Unix crypt command. -<P> -So, while I was lazy with Compress, I'm realistic with Crypt. I'll -show you the hooks and entry points and let someone else contribute an -encryptor. -<HR> -SHAR_EOF - $shar_touch -am 1019213798 'page20.pre' && - chmod 0664 'page20.pre' || - $echo 'restore of' 'page20.pre' 'failed' - if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \ - && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then - md5sum -c << SHAR_EOF >/dev/null 2>&1 \ - || $echo 'page20.pre:' 'MD5 check failed' -7f75130d385a34b2c421a8d7cae69cc3 page20.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page20.pre'`" - test 356 -eq "$shar_count" || - $echo 'page20.pre:' 'original size' '356,' 'current size' "$shar_count!" - fi -fi -# ============= page21.pre ============== -if test -f 'page21.pre' && test "$first_param" != -c; then - $echo 'x -' SKIPPING 'page21.pre' '(file already exists)' -else - $echo 'x -' extracting 'page21.pre' '(text)' - sed 's/^X//' << 'SHAR_EOF' > 'page21.pre' && -The encryption implementation isn't any smarter than that of the -compressor. Still, the hooks are there for you to insert your -favorite library. -<HR> -SHAR_EOF - $shar_touch -am 1019213898 'page21.pre' && - chmod 0664 'page21.pre' || - $echo 'restore of' 'page21.pre' 'failed' - if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \ - && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then - md5sum -c << SHAR_EOF >/dev/null 2>&1 \ - || $echo 'page21.pre:' 'MD5 check failed' -7f0f64452098cdef38c5496340a4b6c7 page21.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page21.pre'`" - test 151 -eq "$shar_count" || - $echo 'page21.pre:' 'original size' '151,' 'current size' "$shar_count!" - fi -fi -# ============= page22.pre ============== -if test -f 'page22.pre' && test "$first_param" != -c; then - $echo 'x -' SKIPPING 'page22.pre' '(file already exists)' -else - $echo 'x -' extracting 'page22.pre' '(text)' - sed 's/^X//' << 'SHAR_EOF' > 'page22.pre' && -Well, this has certainly been one of the more verbose tutorials to -date. I must say "thanks" to everyone who stuck it out this far! -<P> -A quick review of what we've done: -<UL> -X -<LI>Create a simple client application and Client object that uses a -Protocol Stream without really knowing how they work. The app (and -object) rely on the public interface of the Protocol Stream to get the -job done. At this level the protocol details are irrelevant. -<P> -<LI>Next, we create a simple server application and Server object -similar to the client. The Protocol Stream is of course used and we -have to know a little more so that we can insert a <i>reader</i> that -will ultimately process the data from the client. -<P> -<LI>We then go into the details of the Protocol_Stream implementation -and it's Protocol_Task object that forms the basis for the stream -tasks. Each object is kept as small and simple as possible to improve -reusability and future maintenance. -<P> -<LI>Finally, the individual protocol objects are discused. Separate -objects for the peer interface were created as well as the bogus -compressor and encryptor. The protocol can be extended or modified by -creating new such objects and installing them in the Protocol_Stream's -open() method. -X -</UL> -<P> -X -It doesn't sound like much but it certainly took a bunch of files to -get there. It's easy to get lost in the details when there's so much -to cover so you're encouraged to go over things a couple of times. -As always, enhancments of the tutorials is welcome! -<P> -Here's the complete file list: -<UL> -<LI><A HREF="client">Makefile</A> -<P> -<LI><A HREF="Makefile.client">client Makefile</A> -<LI><A HREF="client.cpp">client.cpp</A> -<LI><A HREF="Client_i.h">Client_i.h</A> -<LI><A HREF="Client_i.cpp">Client_i.cpp</A> -<P> -<LI><A HREF="Makefile.server">Server Makefile</A> -<LI><A HREF="server.cpp">server.cpp</A> -<LI><A HREF="Server_i.h">Server_i.h</A> -<LI><A HREF="Server_i.cpp">Server_i.cpp</A> -<LI><A HREF="Handler.h">Handler.h</A> -<LI><A HREF="Handler.cpp">Handler.cpp</A> -<P> -<LI><A HREF="Protocol_Stream.cpp">Protocol_Stream.cpp</A> -<LI><A HREF="Protocol_Stream.h">Protocol_Stream.h</A> -<LI><A HREF="Protocol_Task.cpp">Protocol_Task.cpp</A> -<LI><A HREF="Protocol_Task.h">Protocol_Task.h</A> -<P> -<LI><A HREF="Xmit.cpp">Xmit.cpp</A> -<LI><A HREF="Xmit.h">Xmit.h</A> -<LI><A HREF="Recv.cpp">Recv.cpp</A> -<LI><A HREF="Recv.h">Recv.h</A> -<P> -<LI><A HREF="Compressor.cpp">Compressor.cpp</A> -<LI><A HREF="Compressor.h">Compressor.h</A> -<LI><A HREF="Crypt.cpp">Crypt.cpp</A> -<LI><A HREF="Crypt.h">Crypt.h</A> -</UL> -SHAR_EOF - $shar_touch -am 1022205898 'page22.pre' && - chmod 0664 'page22.pre' || - $echo 'restore of' 'page22.pre' 'failed' - if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \ - && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then - md5sum -c << SHAR_EOF >/dev/null 2>&1 \ - || $echo 'page22.pre:' 'MD5 check failed' -9eae1b08c2e061a68bfc1f3cbc2f59de page22.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page22.pre'`" - test 2567 -eq "$shar_count" || - $echo 'page22.pre:' 'original size' '2567,' 'current size' "$shar_count!" - fi -fi -# ============= page04.pst ============== -if test -f 'page04.pst' && test "$first_param" != -c; then - $echo 'x -' SKIPPING 'page04.pst' '(file already exists)' -else - $echo 'x -' extracting 'page04.pst' '(text)' - sed 's/^X//' << 'SHAR_EOF' > 'page04.pst' && -<HR> -<P> -Ok, that's it for the client. We've seen a very simple main() -X followed by an equally simple Client object. -<P> -For a quick look back: -<UL> -<LI><A HREF="Makefile.client">client Makefile</A> -<LI><A HREF="client.cpp">client.cpp</A> -<LI><A HREF="Client_i.h">Client_i.h</A> -<LI><A HREF="Client_i.cpp">Client_i.cpp</A> -</UL> -<P> -Now we'll move on and examine the server counter-part of our client. -SHAR_EOF - $shar_touch -am 1022205698 'page04.pst' && - chmod 0664 'page04.pst' || - $echo 'restore of' 'page04.pst' 'failed' - if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \ - && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then - md5sum -c << SHAR_EOF >/dev/null 2>&1 \ - || $echo 'page04.pst:' 'MD5 check failed' -00419a8ab9a3ddae3261840b62afdc4a page04.pst -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page04.pst'`" - test 406 -eq "$shar_count" || - $echo 'page04.pst:' 'original size' '406,' 'current size' "$shar_count!" - fi -fi -# ============= page09.pst ============== -if test -f 'page09.pst' && test "$first_param" != -c; then - $echo 'x -' SKIPPING 'page09.pst' '(file already exists)' -else - $echo 'x -' extracting 'page09.pst' '(text)' - sed 's/^X//' << 'SHAR_EOF' > 'page09.pst' && -<HR> -<P> -That's it for the server-specific code. I think I've been fairly -successful in keeping it simple and to the point. There are a couple -of places where the as-yet-undescribed Protocol_Stream pops up and may -cause confusion. We're going to discuss that mystery now but before -we do here's the list of server files if you want to review: -X -<UL> -<LI><A HREF="Makefile.server">Server Makefile</A> -<LI><A HREF="server.cpp">server.cpp</A> -<LI><A HREF="Server_i.h">Server_i.h</A> -<LI><A HREF="Server_i.cpp">Server_i.cpp</A> -<LI><A HREF="Handler.h">Handler.h</A> -<LI><A HREF="Handler.cpp">Handler.cpp</A> -</UL> -<P> -SHAR_EOF - $shar_touch -am 1022205698 'page09.pst' && - chmod 0664 'page09.pst' || - $echo 'restore of' 'page09.pst' 'failed' - if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \ - && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then - md5sum -c << SHAR_EOF >/dev/null 2>&1 \ - || $echo 'page09.pst:' 'MD5 check failed' -a96009f43a6fe8e6b52ffa923993a3e1 page09.pst -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page09.pst'`" - test 617 -eq "$shar_count" || - $echo 'page09.pst:' 'original size' '617,' 'current size' "$shar_count!" - fi -fi -rm -fr _sh31334 -exit 0 diff --git a/docs/tutorials/015/page01.html b/docs/tutorials/015/page01.html deleted file mode 100644 index 098d031d3ad..00000000000 --- a/docs/tutorials/015/page01.html +++ /dev/null @@ -1,104 +0,0 @@ -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 015</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 015</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Building a protocol stream</FONT></B></CENTER> - -<P> -<HR WIDTH="100%"> - -In a typical client/server system you will be sending and receiving - data. That's the whole point after all. -<P> -In the client/server tutorials that we've done so far it was just a - matter of sending a buffer of data to the peer. This was done - with the send*() and recv*() methods of the ACE_SOCK* objects. -<P> -In a more robust system, one might want to process the data before - sending it to a peer and "unprocess" it after reading from a - peer. These processing steps might include encryption, - compression, applying checksums or any number of other actions. -<P> -In this tutorial a Protocol_Stream object is created to encrypt and - compress* data being sent between peers. Both client and server - applications are presented as well. I present the application -level code first and then go into the details of the protocol stream -and it's helper objects. If the stream stuff in the application logic -is confusing then just read on by and come back to it after the later -discussions. -<P> -Disclaimer: -<br> -<ul> -Several folks have reported problems with this tutorial on Win32. -There are a couple of ways to solve this. I've chosen to solve it by -using the ACE_Select_Reactor on all platforms instead of taking the -OS-default. -</ul> -<P> -Kirthika's abstract: -<UL> -The Protocol Stream model consists of a stream layer which pushes the -data towards the underlying SOCK_Stream thru the stages of encryption -and compression. This data is received at the other end of the -SOCK_Stream and sent up to its Protocol_Stream layer via the stages of -decompression and decryption and an optional Reader task. This is very -similar to the model of the TCP/IP stack (specifically the datalink to -physical layer portion). -<P> -ACE_Message_Blocks are used to communicate between the client and the -server across the Protocol Stream, which abstracts the protocol -conformance details. The underlying SOCK_Stream is used to set up the -connection using the ACE_SOCK_Connector class. Once the connector -completes its job, the SOCK_Stream pointer is passed on to the -Protocol Stream which now takes over. The Client has put() and get() -methods to send and receive data from the server. -<P> -The server is implemented using the ACE_Acceptor to listen at the port -for connections and a reactor for delegating events to the appropriate -event handler. The handle_input () method of the handler simply allows -the stream to receive the data and hand it over to the Handler_Task (a -derivative of the ACE_Task) which will then process it. -<P> -The implementation of this Protocol Stream model is done using the -ACE_Module class. The module for Xmit/Recv is shoved in first -into the stream, followed by the compression and encryption modules. The -optional Reader if defined is bundled with a dummy task -(ACE_Thru_Task class) into a module. The get() and put() methods do -the job of reading and writing to the Stream. Each module is made up -of a pair of Protocol Tasks. A Protocol Task is a derivative of the -ACE_Task and whose recv() and send() methods need to be filled to -perform the appropriate task. -<P> -The Xmit object derives from the Protocol task and has a send() method -which does the task of transmitting data to the underlying -SOCK_Stream. Keeping the fragmentation and reassembly issues in mind, -block-size is also sent across with the block of data. -The Recv object uses a dummy Message Block to provoke the Protocol -Task object to call the recv() on it. This is done by being -foresighted about the use of mutliple threads instead of a single -thread. -<P> -The compression/decompression is bundled in a single Protocol Task -object with the send () method doing the compression and the recv() -doing the decompression. Similarly, the encrption/decryption is done -using a single Protocol Task object. -<P> -This tutorial provides a glimpse on how to design and implement a -protocol in layers and also revises a lot of what has been learnt until -now from the previous tutorials. -(for instance, Message_Block, Task, Acceptor, Connector, Event_Handler -etc.) -</UL> -<P> -<font size=-1>* Ok, I didn't really implement encryption and - compression objects. I'll leave that as a thought - exercise!</font> -<P><HR WIDTH="100%"> -<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] [<A HREF="page02.html">Continue This Tutorial</A>]</CENTER> diff --git a/docs/tutorials/015/page02.html b/docs/tutorials/015/page02.html deleted file mode 100644 index 4431fc4cf78..00000000000 --- a/docs/tutorials/015/page02.html +++ /dev/null @@ -1,93 +0,0 @@ -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 015</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 015</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Building a protocol stream</FONT></B></CENTER> - -<P> -<HR WIDTH="100%"> -We'll take a look first at the client application. As usual, our goal - is to keep the main() application as simple as possible and - delegate the tricky stuff to another object. - -<HR> -<PRE> - -<font color=red>// $Id$</font> - -<font color=red>/* The Client object will implement the nasty details of connecting to - communicating with the server -*/</font> -<font color=blue>#include</font> "<font color=green>Client_i.h</font>" - -int main(int argc, char *argv[]) -{ - <font color=red>// How many messages will we send?</font> - int mcount = argc > 1 ? <font color=#008888>ACE_OS::atoi</font>(argv[1]) : 3; - - <font color=red>// Construct a Client with our desired endpoint.</font> - Client client(ACE_DEFAULT_SERVER_PORT,ACE_DEFAULT_SERVER_HOST); - - <font color=red>// Attempt to open the connection to the server.</font> - if( client.open() == -1 ) - { - ACE_ERROR_RETURN ((LM_ERROR, "<font color=green>%p\n</font>", "<font color=green><font color=#008888>Client::open</font>()</font>"), -1); - } - - <font color=red>// Send a few messages to the server and get some responses...</font> - for( int i = 0 ; i < mcount ; ++i ) - { - <font color=red>// Since we'll be using a Protocol Stream (even though we</font> - <font color=red>// don't know that at this level) we require the use of</font> - <font color=red>// ACE_Message_Block objects to send/receive data.</font> - ACE_Message_Block * message = new ACE_Message_Block( 128 ); - - <font color=red>// Construct a silly message to send to the server.</font> - <font color=red>// Notice that we're careful to add one to the strlen() so </font> - <font color=red>// that we also send the end-of-string NULL character.</font> - <font color=#008888>ACE_OS::sprintf</font> (message->wr_ptr (), "<font color=green>This is message %d.</font>", i); - message->wr_ptr (strlen (message->rd_ptr ())+1); - - <font color=red>// client will take ownership of the message block so that </font> - <font color=red>// we don't have to remember to release(). We *do* have</font> - <font color=red>// to remember not to use it after put() since it may be</font> - <font color=red>// released almost immediately.</font> - client.put( message ); - - ACE_Message_Block * response; - - <font color=red>// get() takes an ACE_Message_Block pointer reference. We then</font> - <font color=red>// assume ownership of it and must release() when we're done.</font> - if( client.get( response ) == -1 ) - { - ACE_DEBUG ((LM_INFO, "<font color=green>(%P|%t) Failed to get response from server\n</font>" )); - break; - } - - ACE_DEBUG ((LM_INFO, "<font color=green>(%P|%t) The server's response: (%s)\n</font>", - response->rd_ptr())); - - <font color=red>// Now that we're through with the response we have to</font> - <font color=red>// release() it to avoid memory leaks.</font> - response->release(); - } - - ACE_DEBUG ((LM_INFO, "<font color=green>(%P|%t) Shutting down the stream\n</font>" )); - - <font color=red>// Before we exit, it's a good idea to properly close() the connection.</font> - if( client.close() == -1 ) - { - ACE_ERROR_RETURN ((LM_ERROR, "<font color=green>%p\n</font>", "<font color=green><font color=#008888>Client::close</font>()</font>"), -1); - } - - return(0); -} -</PRE> -<P><HR WIDTH="100%"> -<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] [<A HREF="page03.html">Continue This Tutorial</A>]</CENTER> diff --git a/docs/tutorials/015/page03.html b/docs/tutorials/015/page03.html deleted file mode 100644 index ca92ec3cbcd..00000000000 --- a/docs/tutorials/015/page03.html +++ /dev/null @@ -1,97 +0,0 @@ -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 015</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 015</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Building a protocol stream</FONT></B></CENTER> - -<P> -<HR WIDTH="100%"> -The Client object is designed to hide all of the messy connection - logic from it's users. It also provides put/get methods for - sending data to the server and receiving the server's response. - Note the Protocol_Stream member that will take care of - converting and sending/receiving the data. -<HR> -<PRE> -<font color=red>// $Id$</font> - -<font color=blue>#ifndef</font> <font color=purple>CLIENT_H</font> -<font color=blue>#define</font> <font color=purple>CLIENT_H</font> - -<font color=blue>#include</font> "<A HREF="../../../ace/SOCK_Stream.h">ace/SOCK_Stream.h</A>" - -<font color=blue>#if !defined</font> (<font color=purple>ACE_LACKS_PRAGMA_ONCE</font>) -<font color=blue># pragma</font> <font color=purple>once</font> -<font color=blue>#endif</font> <font color=red>/* ACE_LACKS_PRAGMA_ONCE */</font> - -<font color=blue>#include</font> "<font color=green>Protocol_Stream.h</font>" - -class ACE_Message_Block; - -<font color=red>/* Hide the details of connection and protocol-conformance from the - application-level logic. -*/</font> -class Client -{ -public: - <font color=red>// Provide the server information when constructing the</font> - <font color=red>// object. This could (and probably should) be moved to the</font> - <font color=red>// open() method.</font> - Client (u_short port, - const char *server); - - <font color=red>// Cleanup...</font> - ~Client (void); - - <font color=red>// Open the connection to the server.</font> - int open (void); - - <font color=red>// Close the connection to the server. Be sure to do this</font> - <font color=red>// before you let the Client go out of scope.</font> - int close (void); - - <font color=red>// Put a message to the server. The Client assumes ownership of</font> - <font color=red>// <message> at that point and will release() it when done. Do not</font> - <font color=red>// use <message> after passing it to put().</font> - int put (ACE_Message_Block *message); - - <font color=red>// Get a response from the server. The caller becomes the owner of</font> - <font color=red>// <response> after this call and is responsible for invoking</font> - <font color=red>// release() when done.</font> - int get (ACE_Message_Block *&response); - -private: - <font color=red>// Protocol_Stream hides the protocol conformance details from us.</font> - Protocol_Stream stream_; - - <font color=red>// We create a connection on the peer_ and then pass ownership of it</font> - <font color=red>// to the protocol stream.</font> - ACE_SOCK_Stream peer_; - - <font color=red>// Endpoing information saved by the constructor for use by open().</font> - u_short port_; - const char *server_; - - <font color=red>// Accessors for the complex member variables.</font> - - Protocol_Stream &stream (void) - { - return this->stream_; - } - - ACE_SOCK_Stream &peer (void) - { - return this->peer_; - } -}; - -<font color=blue>#endif</font> <font color=red>/* CLIENT_H */</font> -</PRE> -<P><HR WIDTH="100%"> -<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] [<A HREF="page04.html">Continue This Tutorial</A>]</CENTER> diff --git a/docs/tutorials/015/page04.html b/docs/tutorials/015/page04.html deleted file mode 100644 index b538dc65bc8..00000000000 --- a/docs/tutorials/015/page04.html +++ /dev/null @@ -1,96 +0,0 @@ -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 015</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 015</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Building a protocol stream</FONT></B></CENTER> - -<P> -<HR WIDTH="100%"> -The implementation of the Client object. Only the open() method - really does any work. The other methods simply delegate their - function to the Protocol_Stream. -<HR> -<PRE> - -<font color=red>// $Id$</font> - -<font color=blue>#include</font> "<font color=green>Client_i.h</font>" -<font color=blue>#include</font> "<A HREF="../../../ace/Message_Block.h">ace/Message_Block.h</A>" -<font color=blue>#include</font> "<A HREF="../../../ace/INET_Addr.h">ace/INET_Addr.h</A>" -<font color=blue>#include</font> "<A HREF="../../../ace/SOCK_Connector.h">ace/SOCK_Connector.h</A>" - -<font color=red>// Simple constructor just remembers the endpoint information for use by open.</font> -<font color=#008888>Client::Client</font>( u_short _port, const char * _server) - : port_(_port), server_(_server) -{ - ; -} - -<font color=red>/* Do nothing. This should probably call close() if we can make sure - that it's OK to close() multiple times. -*/</font> -<font color=#008888>Client::~Client</font>(void) -{ - ; -} - -<font color=red>/* Open the connection to the server. This is traditional ACE. We - simply construct an endpoint and use a connector to establish the - link. -*/</font> -int <font color=#008888>Client::open</font>( void ) -{ - ACE_INET_Addr addr(port_,server_); - ACE_SOCK_Connector con; - - if( con.connect(peer(),addr) == -1 ) - { - ACE_ERROR_RETURN ((LM_ERROR, "<font color=green>%p\n</font>", "<font color=green><font color=#008888>ACE_SOCK_Connector::connect</font>()</font>"), -1); - } - - <font color=red>// Something new here... We have to use the protocol stream</font> - <font color=red>// to ensure that our data is in the correct format when</font> - <font color=red>// received by the server. Thus, we open the stream and</font> - <font color=red>// transfer ownership of the peer.</font> - return stream().open( peer() ); -} - -<font color=red>// The remainder of the functions just delegate to the stream.</font> - -int <font color=#008888>Client::close</font>( void ) -{ - return stream().close(); -} - -int <font color=#008888>Client::put</font>( ACE_Message_Block * _message ) -{ - return stream().put(_message,0); -} - -int <font color=#008888>Client::get</font>( ACE_Message_Block * & _response ) -{ - return stream().get(_response); -} -</PRE> -<HR> -<P> -Ok, that's it for the client. We've seen a very simple main() - followed by an equally simple Client object. -<P> -For a quick look back: -<UL> -<LI><A HREF="Makefile.client">client Makefile</A> -<LI><A HREF="client.cpp">client.cpp</A> -<LI><A HREF="Client_i.h">Client_i.h</A> -<LI><A HREF="Client_i.cpp">Client_i.cpp</A> -</UL> -<P> -Now we'll move on and examine the server counter-part of our client. -<P><HR WIDTH="100%"> -<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] [<A HREF="page05.html">Continue This Tutorial</A>]</CENTER> diff --git a/docs/tutorials/015/page05.html b/docs/tutorials/015/page05.html deleted file mode 100644 index dbfe16e91d7..00000000000 --- a/docs/tutorials/015/page05.html +++ /dev/null @@ -1,93 +0,0 @@ -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 015</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 015</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Building a protocol stream</FONT></B></CENTER> - -<P> -<HR WIDTH="100%"> -Like the client, we want to keep the main() part of our server code as - simple as possible. This is done by putting most of the work - into the Handler object that will deal with client connections. -From the looks of the code below, I think we've been successful in our -simplification. -<HR> - -<PRE> - -<font color=red>// $Id$</font> - -<font color=blue>#include</font> "<font color=green>Server_i.h</font>" -<font color=blue>#include</font> "<A HREF="../../../ace/Select_Reactor.h">ace/Select_Reactor.h</A>" - -<font color=red>// A signal handler that will close the server object</font> -extern "<font color=green>C</font>" void handler (int) -{ - <font color=#008888>Server::close</font>(); -} - -int main (int, char **) -{ - <font color=red>/* On Win32, the WFMO reactor is used by default. - Unfortunately, that causes the sockets to be put into - non-blocking mode which will break <font color=#008888>Recv::recv</font>(). To - prevent that issue, I explicitly use the Select Reactor - instead. I'll talk more about the "<font color=green>problem</font>" in the Recv - comments. - */</font> - - <font color=red>// First, we create a Select_Reactor that will do the work.</font> - <font color=red>// To keep things simple, I'll create it on the stack.</font> - ACE_Select_Reactor mySelectReactor; - - <font color=red>// Next, we need an ACE_Reactor that is the bridge between the </font> - <font color=red>// code and the real reactor. It is given a pointer to the</font> - <font color=red>// real reactor.</font> - ACE_Reactor myReactor (&mySelectReactor); - - <font color=red>// Finally, we set the singleton instance to use the reactor</font> - <font color=red>// we've created.</font> - <font color=#008888>ACE_Reactor::instance</font> (&myReactor); - - <font color=red>// The server object that abstracts away all of the difficult parts.</font> - Server server; - - <font color=red>// Attempt to open the server. Like all good ACE-based</font> - <font color=red>// objects, we'll get -1 on failure.</font> - if( server.open() == -1 ) - { - ACE_ERROR_RETURN ((LM_ERROR, "<font color=green>%p\n</font>", "<font color=green>server.open()</font>"), -1); - } - - <font color=red>// Install a signal handler for ^C so that we can exit gracefully</font> - ACE_Sig_Action sa ((ACE_SignalHandler) handler, SIGINT); - - <font color=red>// Run the server's main loop until we're interrupted</font> - if( server.run() == -1 ) - { - ACE_ERROR_RETURN ((LM_ERROR, "<font color=green>%p\n</font>", "<font color=green>server.run()</font>"), -1); - } - - return 0; -} - -<font color=red>/* These explicit instantiations were taken from an earlier tutorial. - Your compiler may require others as well. -*/</font> -<font color=blue>#if defined</font> (<font color=purple>ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION</font>) -template class ACE_Acceptor <Handler, ACE_SOCK_ACCEPTOR>; -template class ACE_Svc_Handler<ACE_SOCK_STREAM, ACE_NULL_SYNCH>; -<font color=blue>#elif defined</font> (<font color=purple>ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA</font>) -<font color=blue>#pragma</font> <font color=purple>instantiate</font> ACE_Acceptor <Handler, ACE_SOCK_ACCEPTOR> -<font color=blue>#pragma</font> <font color=purple>instantiate</font> ACE_Svc_Handler<ACE_SOCK_STREAM, ACE_NULL_SYNCH> -<font color=blue>#endif</font> <font color=red>/* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */</font> - -</PRE> -<P><HR WIDTH="100%"> -<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] [<A HREF="page06.html">Continue This Tutorial</A>]</CENTER> diff --git a/docs/tutorials/015/page06.html b/docs/tutorials/015/page06.html deleted file mode 100644 index 8ffa8bdb12e..00000000000 --- a/docs/tutorials/015/page06.html +++ /dev/null @@ -1,77 +0,0 @@ -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 015</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 015</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Building a protocol stream</FONT></B></CENTER> - -<P> -<HR WIDTH="100%"> -The Server object exists in order simplify the -main() application level. To that end, it hides the details of -creating an acceptor and managing the reactor. -<P> -The static close() method available for a signal handler as you saw on -the previous page. Of course the assumption here is that there would -only be one Server instance but since you can't provide a TCP/IP port, -that's probably a valid assumption! -<HR> -<PRE> -<font color=red>// $Id$</font> - -<font color=blue>#ifndef</font> <font color=purple>SERVER_H</font> -<font color=blue>#define</font> <font color=purple>SERVER_H</font> - -<font color=blue>#include</font> "<A HREF="../../../ace/Acceptor.h">ace/Acceptor.h</A>" - -<font color=blue>#if !defined</font> (<font color=purple>ACE_LACKS_PRAGMA_ONCE</font>) -<font color=blue># pragma</font> <font color=purple>once</font> -<font color=blue>#endif</font> <font color=red>/* ACE_LACKS_PRAGMA_ONCE */</font> - -<font color=blue>#include</font> "<A HREF="../../../ace/SOCK_Acceptor.h">ace/SOCK_Acceptor.h</A>" -<font color=blue>#include</font> "<font color=green>Handler.h</font>" - -<font color=red>/* Anytime I have templates I try to remember to create a typedef for - the parameterized object. It makes for much less typing later! -*/</font> -typedef ACE_Acceptor <Handler, ACE_SOCK_ACCEPTOR> Acceptor; - -class Server -{ -public: - <font color=red>// Our simple constructor takes no parameters. To make the</font> - <font color=red>// server a bit more useful, you may want to pass in the</font> - <font color=red>// TCP/IP port to be used by the acceptor.</font> - Server (void); - ~Server (void); - - <font color=red>// Open the server for business</font> - int open (void); - - <font color=red>// Close all server instances by setting the finished_ flag.</font> - <font color=red>// Actually, the way this class is written, you can only have</font> - <font color=red>// one instance.</font> - static int close (void); - - <font color=red>// Run the server's main loop. The use of the gloabl ACE_Reactor by</font> - <font color=red>// this method is what limits us to one Server instance.</font> - int run (void); - -private: - <font color=red>// This will accept client connection requests and instantiate a</font> - <font color=red>// Handler object for each new connection.</font> - Acceptor acceptor_; - - <font color=red>// Our shutdown flag</font> - static sig_atomic_t finished_; -}; - -<font color=blue>#endif</font> <font color=red>/* SERVER_H */</font> -</PRE> -<P><HR WIDTH="100%"> -<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] [<A HREF="page07.html">Continue This Tutorial</A>]</CENTER> diff --git a/docs/tutorials/015/page07.html b/docs/tutorials/015/page07.html deleted file mode 100644 index 06633974eb6..00000000000 --- a/docs/tutorials/015/page07.html +++ /dev/null @@ -1,100 +0,0 @@ -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 015</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 015</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Building a protocol stream</FONT></B></CENTER> - -<P> -<HR WIDTH="100%"> -And now the implementation of Server. This is actually just the -main() code from a previous tutorial broken into appropriate method -calls. It may seem silly to do this rather than keeping the stuff in -main() but you'll find that you have less trouble enhancing an -application when you take this sort of approach. -<HR> - -<PRE> - -<font color=red>// $Id$</font> - -<font color=blue>#include</font> "<font color=green>Server_i.h</font>" - -<font color=red>/* We have to allocate space for our static finished_ flag. We also - initialize it to 'false' so that we don't exit immediately. -*/</font> -sig_atomic_t <font color=#008888>Server::finished_</font> = 0; - -<font color=red>/* The simple constructor and destructor don't do anything but give us - a place to expand in the future if we want. -*/</font> -<font color=#008888>Server::Server</font>(void) -{ - ; -} - -<font color=#008888>Server::~Server</font>(void) -{ - ; -} - -<font color=red>/* Opening the server is as simple as opening the acceptor with the - default ACE_Reactor instance. If we want to allow multiple - instances of Server objects then we should have an ACE_Reactor - member variable that we can register with. -*/</font> -int <font color=#008888>Server::open</font>(void) -{ - if (acceptor_.open (ACE_INET_Addr (ACE_DEFAULT_SERVER_PORT), <font color=#008888>ACE_Reactor::instance</font>()) == -1) - ACE_ERROR_RETURN ((LM_ERROR, "<font color=green>%p\n</font>", "<font color=green>open</font>"), -1); - - return(0); -} - -<font color=red>/* Running the server just means that we execute the basic event - loop for the reactor. Again, if we had a private reactor then we - could have multiple server's in their run() method. -*/</font> -int <font color=#008888>Server::run</font>(void) -{ - ACE_DEBUG ((LM_DEBUG, "<font color=green>(%P|%t) starting up server daemon\n</font>")); - - <font color=red>// Here's the basic event loop. I have a 2-second timeout on</font> - <font color=red>// the handle_events() so that we don't have to wait too long</font> - <font color=red>// when we set the finished_ flag.</font> - while (!finished_) - { - <font color=red>// Some (all?) platforms return the "<font color=green>remaining time</font>" in the</font> - <font color=red>// timeout parameter. If we don't reset it each time, we</font> - <font color=red>// will end up with a 100% CPU spin loop!</font> - ACE_Time_Value timeout(2); - - <font color=#008888>ACE_Reactor::instance</font>()->handle_events (&timeout); - } - - <font color=red>// Close the acceptor when we're done. This may be handled by </font> - <font color=red>// the framework but it's good practice to be explicit about things.</font> - acceptor_.close(); - - ACE_DEBUG ((LM_DEBUG, "<font color=green>(%P|%t) shutting down server daemon\n</font>")); - - return 0; -} - -<font color=red>/* The close() method simply sets the finished_ flag so that run() - will leave the event loop and exit. -*/</font> -int <font color=#008888>Server::close</font>(void) -{ - finished_ = 1; - <font color=#008888>ACE_Reactor::instance</font>()->notify(); - return(0); -} -</PRE> -<P><HR WIDTH="100%"> -<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] [<A HREF="page08.html">Continue This Tutorial</A>]</CENTER> diff --git a/docs/tutorials/015/page08.html b/docs/tutorials/015/page08.html deleted file mode 100644 index 127bab8f00c..00000000000 --- a/docs/tutorials/015/page08.html +++ /dev/null @@ -1,89 +0,0 @@ -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 015</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 015</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Building a protocol stream</FONT></B></CENTER> - -<P> -<HR WIDTH="100%"> -The Handler object is our event handler. You can use either -ACE_Event_Handler or ACE_Svc_Handler<> for the baseclass. I generally -prefer the latter since it takes care of some housekeeping that I -would otherwise be responsible for. -<P> -The class declaration is taken almost exactly from a previous -tutorial. A good design will have a simple handler object that will -collect data from the peer and pass it along to another object for -processing. Again, keep it simple and delegate authority. -<HR> -<PRE> -<font color=red>// $Id$</font> - -<font color=blue>#ifndef</font> <font color=purple>HANDLER_H</font> -<font color=blue>#define</font> <font color=purple>HANDLER_H</font> - -<font color=blue>#include</font> "<A HREF="../../../ace/Svc_Handler.h">ace/Svc_Handler.h</A>" - -<font color=blue>#if !defined</font> (<font color=purple>ACE_LACKS_PRAGMA_ONCE</font>) -<font color=blue># pragma</font> <font color=purple>once</font> -<font color=blue>#endif</font> <font color=red>/* ACE_LACKS_PRAGMA_ONCE */</font> - -<font color=blue>#include</font> "<A HREF="../../../ace/SOCK_Stream.h">ace/SOCK_Stream.h</A>" -<font color=blue>#include</font> "<font color=green>Protocol_Stream.h</font>" - -<font color=red>/* Just your basic event handler. We use ACE_Svc_Handler<> as a - baseclass so that it can maintain the peer() and other details for - us. We're not going to activate() this object, so we can get away - with the NULL synch choice. */</font> -class Handler : public ACE_Svc_Handler <ACE_SOCK_STREAM, ACE_NULL_SYNCH> -{ -public: - Handler (void); - ~Handler (void); - - <font color=red>// Called by the acceptor when we're created in response to a client</font> - <font color=red>// connection.</font> - int open (void *); - - <font color=red>// Called when it's time for us to be deleted. We take care of</font> - <font color=red>// removing ourselves from the reactor and shutting down the peer()</font> - <font color=red>// connectin.</font> - void destroy (void); - - <font color=red>// Called when it's time for us to go away. There are subtle</font> - <font color=red>// differences between destroy() and close() so don't try to use</font> - <font color=red>// either for all cases.</font> - int close (u_long); - -protected: - <font color=red>// Respond to peer() activity.</font> - int handle_input (ACE_HANDLE); - - <font color=red>// This will be called when handle_input() returns a failure code.</font> - <font color=red>// That's our signal that it's time to begin the shutdown process.</font> - int handle_close (ACE_HANDLE, - ACE_Reactor_Mask mask); -private: - - <font color=red>// Like the Client, we have to abide by the protocol requirements.</font> - <font color=red>// We use a local Protocol_Stream object to take care of those</font> - <font color=red>// details. For us, I/O then just becomes a matter of interacting</font> - <font color=red>// with the stream.</font> - Protocol_Stream stream_; - - Protocol_Stream &stream (void) - { - return this->stream_; - } -}; - -<font color=blue>#endif</font> <font color=red>/* HANDLER_H */</font> -</PRE> -<P><HR WIDTH="100%"> -<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] [<A HREF="page09.html">Continue This Tutorial</A>]</CENTER> diff --git a/docs/tutorials/015/page09.html b/docs/tutorials/015/page09.html deleted file mode 100644 index b8156b13271..00000000000 --- a/docs/tutorials/015/page09.html +++ /dev/null @@ -1,225 +0,0 @@ -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 015</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 015</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Building a protocol stream</FONT></B></CENTER> - -<P> -<HR WIDTH="100%"> -Like any other event handler, the handle_input() method will be -responsible for getting data from the peer() and doing something with -it. In this case, we have a Protocol_Stream to deal with. We'll use -the stream for the actual I/O but we are ultimately responsible for -processing the data from the peer. To do that, we've created a -Handler_Task that fits within the Protocol_Stream framework to process -data that has been received. Handler::handle_input() will tell the stream that -it's time to read data and that data will eventually show up at -Handler_Task::recv() where we'll process it as required by our -application logic. -<HR> -<PRE> - -<font color=red>// $Id$</font> - -<font color=blue>#include</font> "<font color=green>Handler.h</font>" -<font color=blue>#include</font> "<font color=green>Protocol_Task.h</font>" - -<font color=red>/* The Protocol_Stream gives us the option to insert a Protocol_Task - to process data received by the stream. We'll get into the details - more when we talk about the stream in detail. For now it's enough - to know that <font color=#008888>Handler_Task::recv</font>() will be invoked by the stream - after data from the client has been received and processed (eg -- - decrypted, uncompressed, and whatever else the protocol requires.) -*/</font> -class Handler_Task : public Protocol_Task -{ -public: - - <font color=red>// Typical...</font> - typedef Protocol_Task inherited; - - <font color=red>// Simple...</font> - Handler_Task(void); - ~Handler_Task(void); - -protected: - - <font color=red>// recv() is invoked after received data has been fully</font> - <font color=red>// processed by the protocol rules. Data processing typically </font> - <font color=red>// done in handle_input() can then be done here.</font> - int recv(ACE_Message_Block * message, - ACE_Time_Value *timeout = 0); -}; - -<font color=#008888>Handler::Handler</font>(void) -{ - ; -} - -<font color=#008888>Handler::~Handler</font>(void) -{ - ; -} - -<font color=red>/* The Acceptor will open() us once the peer() connection is - established. There are a couple of things we have to do here - before we're ready to receive data from the client. -*/</font> -int <font color=#008888>Handler::open</font> (void *) -{ - ACE_INET_Addr addr; - - <font color=red>// Make sure that we can get the peer's address. If we can't</font> - <font color=red>// then there may be a network error or something else that</font> - <font color=red>// will prevent communicating with the client. This is</font> - <font color=red>// something you'll want to do in every event handler you create.</font> - if (this->peer ().get_remote_addr (addr) == -1) - ACE_ERROR_RETURN ((LM_ERROR, "<font color=green>(%P|%t) Cannot get remote addr\n</font>"), -1); - - <font color=red>// Announce the client</font> - ACE_DEBUG ((LM_DEBUG, "<font color=green>(%P|%t) connected with %s\n</font>", addr.get_host_name() )); - - <font color=red>// Here's the first new twist to the old event handler.</font> - <font color=red>// Before we can use the Protocol_Stream to communicate with</font> - <font color=red>// the peer, we must open() it. We provide the stream with</font> - <font color=red>// the peer() so that it will have a valid socket on which to</font> - <font color=red>// read client requests and send our responses. We also</font> - <font color=red>// provide a Handler_Task instance that will ultimately be</font> - <font color=red>// responsible for processing any client data we receive.</font> - int rval = stream().open( this->peer(), new Handler_Task() ); - - <font color=red>// Of course, we have to account for the chance that the</font> - <font color=red>// stream's open() may fail.</font> - if( rval == -1 ) - { - ACE_ERROR_RETURN ((LM_ERROR, "<font color=green>(%P|%t) Cannot open the protocol stream.\n</font>"), -1); - } - - <font color=red>// Now that we know the client is valid and that the stream is </font> - <font color=red>// ready for business we can register with the gloabl reactor</font> - <font color=red>// instance. Here again is an opportunity for improvement if</font> - <font color=red>// we expect to have mulitple Server object instances.</font> - if (<font color=#008888>ACE_Reactor::instance</font>()->register_handler (this, ACE_Event_Handler::READ_MASK) == -1) - ACE_ERROR_RETURN ((LM_ERROR, "<font color=green>(%P|%t) Cannot register with reactor\n</font>"), -1); - - return rval; -} - -<font color=red>/* This is a fairly typical destroy() method that can be shared by - both close() and handle_close(). -*/</font> -void <font color=#008888>Handler::destroy</font> (void) -{ - <font color=#008888>ACE_Reactor::instance</font>()->remove_handler(this,ACE_Event_Handler::READ_MASK|ACE_Event_Handler::DONT_CALL); - - this->peer ().close (); - - delete this; -} - -<font color=red>/* In this simple application we just forward the close() and - handle_close() requests right on to the destroy() method. -*/</font> - -int <font color=#008888>Handler::close</font> (u_long) -{ - this->destroy (); - return 0; -} - -int <font color=#008888>Handler::handle_close</font>(ACE_HANDLE, ACE_Reactor_Mask _mask) -{ - this->destroy(); - return 0; -} - -<font color=red>/* Unlike a "<font color=green>traditional</font>" handle_input() ours is very simple. Because - of the use of the protocol stream, we delegate the read function to - the stream's get() and rely on our Handler_Task to do the real work. -*/</font> -int <font color=#008888>Handler::handle_input</font> (ACE_HANDLE) -{ - ACE_DEBUG ((LM_DEBUG, "<font color=green>(%P|%t) Activity from client\n</font>" )); - - <font color=red>// This will cause a blocking read from the peer(). The data</font> - <font color=red>// will then be pushed through the protocol stream.</font> - if( stream().get( ) == -1 ) - { - ACE_ERROR_RETURN ((LM_ERROR, "<font color=green>(%P|%t) Cannot get data from protocol stream\n</font>"), -1); - } - - return 0; -} - -<font color=red>/* A Protocol_Task is derived from ACE_Task and has the option of - running in one or more threads. I've chosen here to construct the - baseclass with no threads but it should work just fine with one or - more if you need. Unless you're sharing the Handler_Task with - several peers, however, you're probably just wasting a thread to - activate it. On the other hand, if your reactor is running in a - single thread (as in this example) then you can easily implement - thread-per-connection concurrency by giving the baseclass one thread. -*/</font> -<font color=#008888>Handler_Task::Handler_Task</font>(void) - : inherited() -{ - ; -} - -<font color=#008888>Handler_Task::~Handler_Task</font>(void) -{ - ; -} - -<font color=red>/* When installed into the protocol stream, the Handler_Task's recv() - method will be called when data is ready for processing. - */</font> -int <font color=#008888>Handler_Task::recv</font>(ACE_Message_Block * message, - ACE_Time_Value *timeout ) -{ - <font color=red>// Announce the request we got from the client</font> - ACE_DEBUG ((LM_INFO, "<font color=green>(%P|%t) <font color=#008888>Handler_Task::recv</font>() got (%s)\n</font>", message->rd_ptr() )); - - <font color=red>// Create a response message to send to the client</font> - ACE_Message_Block * response = new ACE_Message_Block( 128 ); - - <font color=red>// Nothing very original about this I'm afraid...</font> - <font color=#008888>ACE_OS::sprintf</font>( response->wr_ptr(), "<font color=green>You Said: (%s)</font>", message->rd_ptr() ); - response->wr_ptr( strlen(response->wr_ptr())+1 ); - - <font color=red>// Release the original message block now that we're through</font> - <font color=red>// "<font color=green>processing</font>" it.</font> - message->release(); - - <font color=red>// Turn the message around and send it back down the Stream.</font> - <font color=red>// In other words, we invoke the put() method on the</font> - <font color=red>// Protocol_Stream without having to have a direct reference</font> - <font color=red>// to the stream object.</font> - return this->reply( response, timeout ); -} -</PRE> -<HR> -<P> -That's it for the server-specific code. I think I've been fairly -successful in keeping it simple and to the point. There are a couple -of places where the as-yet-undescribed Protocol_Stream pops up and may -cause confusion. We're going to discuss that mystery now but before -we do here's the list of server files if you want to review: - -<UL> -<LI><A HREF="Makefile.server">Server Makefile</A> -<LI><A HREF="server.cpp">server.cpp</A> -<LI><A HREF="Server_i.h">Server_i.h</A> -<LI><A HREF="Server_i.cpp">Server_i.cpp</A> -<LI><A HREF="Handler.h">Handler.h</A> -<LI><A HREF="Handler.cpp">Handler.cpp</A> -</UL> -<P> -<P><HR WIDTH="100%"> -<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] [<A HREF="page10.html">Continue This Tutorial</A>]</CENTER> diff --git a/docs/tutorials/015/page10.html b/docs/tutorials/015/page10.html deleted file mode 100644 index 3d012c0e970..00000000000 --- a/docs/tutorials/015/page10.html +++ /dev/null @@ -1,126 +0,0 @@ -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 015</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 015</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Building a protocol stream</FONT></B></CENTER> - -<P> -<HR WIDTH="100%"> -And so finally we come to the Protocol_Stream. That, after all, is -the focus of the entire tutorial but it took us half of the day to get -here! -<P> -The Protocol_Stream uses an ACE_Stream to move an ACE_Message_Block -through a series of tasks. Each task in the stream is responsible for -performing some operation on the data in the message block. That is -the nature of a protocol stream (or "stack" if you prefer). In this -stream, the data is compressed and encrypted* on its way between -peers. We also allow users of the stream to install a reader task to -handle data that percolates up from the peer. As you saw a page or -two ago, this is most useful for a server. - -<P> -<font size=-1>*Again, I just pretend to do these things. It would -take another day or two to go through any sort of reasonable -encryption or compression!</font> -<P> -Before we get into the code, here's a picture that's shows what's -going on here. -<P><center><img src="stream.gif"></center></p> -<HR> -<PRE> -<font color=red>// $Id$</font> - -<font color=blue>#ifndef</font> <font color=purple>PROTOCOL_STREAM_H</font> -<font color=blue>#define</font> <font color=purple>PROTOCOL_STREAM_H</font> - -<font color=blue>#include</font> "<A HREF="../../../ace/SOCK_Stream.h">ace/SOCK_Stream.h</A>" - -<font color=blue>#if !defined</font> (<font color=purple>ACE_LACKS_PRAGMA_ONCE</font>) -<font color=blue># pragma</font> <font color=purple>once</font> -<font color=blue>#endif</font> <font color=red>/* ACE_LACKS_PRAGMA_ONCE */</font> - -<font color=blue>#include</font> "<A HREF="../../../ace/Stream.h">ace/Stream.h</A>" - -<font color=red>// Shorthand for the stream.</font> -typedef ACE_Stream<ACE_MT_SYNCH> Stream; - -<font color=red>// Forward references to cut down on the number of <font color=blue>#include</font>s</font> -class ACE_Message_Block; -class Recv; -class Protocol_Task; - -<font color=red>/* The Protocol_Stream provides a tidy interface to an ACE_Stream - setup to process a data block through a series of protocol stages. -*/</font> -class Protocol_Stream -{ -public: - Protocol_Stream (void); - ~Protocol_Stream (void); - - <font color=red>// Provide the stream with an ACE_SOCK_Stream on which it can</font> - <font color=red>// communicate. If _reader is non-null, it will be added as the</font> - <font color=red>// reader task just below the stream head so that it can process</font> - <font color=red>// data read from the peer.</font> - int open (ACE_SOCK_Stream &peer, - Protocol_Task *reader = 0); - - <font color=red>// Close the stream. All of the tasks & modules will also be</font> - <font color=red>// closed.</font> - int close (void); - - <font color=red>// putting data onto the stream will pass it through all protocol</font> - <font color=red>// levels and send it to the peer.</font> - int put (ACE_Message_Block *&message, - ACE_Time_Value *timeout = 0); - - <font color=red>// get will cause the Recv task (at the tail of the stream) to read</font> - <font color=red>// some data from the peer and pass it upstream. The message block</font> - <font color=red>// is then taken from the stream reader task's message queue.</font> - int get (ACE_Message_Block *&response, - ACE_Time_Value *timeout = 0); - - <font color=red>// Tell the Recv task to read some data and send it upstream. The</font> - <font color=red>// data will pass through the protocol tasks and be queued into the</font> - <font color=red>// stream head reader task's message queue. If you've installed a</font> - <font color=red>// _reader in open() then that task's recv() method will see the</font> - <font color=red>// message and may consume it instead of passing it to the stream</font> - <font color=red>// head for queueing.</font> - int get (void); - - ACE_SOCK_Stream &peer (void) - { - return this->peer_; - } - -private: - <font color=red>// Our peer connection</font> - ACE_SOCK_Stream peer_; - - <font color=red>// The stream managing the various protocol tasks</font> - Stream stream_; - - <font color=red>// A task which is capable of receiving data on a socket.</font> - <font color=red>// Note that this is only useful by client-side applications.</font> - Recv *recv_; - - Stream &stream (void) - { - return this->stream_; - } - - <font color=red>// Install the protocol tasks into the stream.</font> - int open (void); -}; - -<font color=blue>#endif</font> <font color=red>/* PROTOCOL_STREAM_H */</font> -</PRE> -<P><HR WIDTH="100%"> -<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] [<A HREF="page11.html">Continue This Tutorial</A>]</CENTER> diff --git a/docs/tutorials/015/page11.html b/docs/tutorials/015/page11.html deleted file mode 100644 index 31eb52bac2d..00000000000 --- a/docs/tutorials/015/page11.html +++ /dev/null @@ -1,219 +0,0 @@ -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 015</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 015</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Building a protocol stream</FONT></B></CENTER> - -<P> -<HR WIDTH="100%"> -And now the implementation of the Protocol_Stream. There are more -lines of code here than we've seen so far but it still isn't -complicated. The basic idea is to construct the ACE_Stream with our -set of protocol objects that will manipulate the data. Our primary -concern in this file is to get everything in the correct order! -<HR> -<PRE> -<font color=red>// $Id$</font> - -<font color=blue>#include</font> "<font color=green>Protocol_Stream.h</font>" -<font color=blue>#include</font> "<font color=green>Protocol_Task.h</font>" - -<font color=blue>#include</font> "<font color=green>Xmit.h</font>" -<font color=blue>#include</font> "<font color=green>Recv.h</font>" - -<font color=blue>#include</font> "<font color=green>Compressor.h</font>" -<font color=blue>#include</font> "<font color=green>Crypt.h</font>" - -<font color=blue>#include</font> "<A HREF="../../../ace/Stream_Modules.h">ace/Stream_Modules.h</A>" - -<font color=red>/* You can choose at compile time to include/exclude the protocol - pieces. -*/</font> -<font color=blue>#define</font> <font color=purple>ENABLE_COMPRESSION</font> -<font color=blue>#define</font> <font color=purple>ENABLE_ENCRYPTION</font> - -<font color=red>// The usual typedefs to make things easier to type.</font> -typedef ACE_Module<ACE_MT_SYNCH> Module; -typedef ACE_Thru_Task<ACE_MT_SYNCH> Thru_Task; - -<font color=red>/* An ACE_Stream is a collection of ACE_Modules. You can think of it - as a doubly-linked list if you like. Each Module contains two - ACE_Task derivatives. One of these tasks is used when sending data - "<font color=green>upstream</font>", the other is used for "<font color=green>downstream</font>" operation. In some - cases, you'll only need to move data in one direction. To provide - a placeholder for the other direction, ACE_Thru_Task can be used. - ACE_Thru_Task responds to the put() by simply invoking put_next() - to send the data to the next module. - */</font> - -<font color=red>/* Do-nothing constructor and destructor - */</font> - -<font color=#008888>Protocol_Stream::Protocol_Stream</font> (void) -{ -} - -<font color=#008888>Protocol_Stream::~Protocol_Stream</font> (void) -{ -} - -<font color=red>/* Even opening the stream is rather simple. The important thing to - remember is that the modules you push onto the stream first will be - at the tail (eg -- most downstream) end of things when you're - done. - */</font> -int -<font color=#008888>Protocol_Stream::open</font> (ACE_SOCK_Stream &peer, - Protocol_Task *reader) -{ - <font color=red>// Initialize our peer() to read/write the socket we're given</font> - peer_.set_handle (peer.get_handle ()); - - <font color=red>// Construct (and remember) the Recv object so that we can read from</font> - <font color=red>// the peer().</font> - ACE_NEW_RETURN (recv_, - Recv ( this->peer ()), - -1); - - <font color=red>// Add the transmit and receive tasks to the head of the stream. As</font> - <font color=red>// we add more modules these will get pushed downstream and end up</font> - <font color=red>// nearest the tail by the time we're done.</font> - if (stream ().push (new Module ("<font color=green>Xmit/Recv</font>", - new Xmit ( this->peer ()), - recv_)) == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "<font color=green>%p\n</font>", - "<font color=green>stream().push(xmit/recv)</font>"), - -1); - - <font color=red>// Add any other protocol tasks to the stream. Each one is added at</font> - <font color=red>// the head. The net result is that Xmit/Recv are at the tail.</font> - if (this->open () == -1) - return -1; - - <font color=red>// If a reader task was provided then push that in as the upstream</font> - <font color=red>// side of the next-to-head module. Any data read from the peer()</font> - <font color=red>// will be sent through here last. Server applications will</font> - <font color=red>// typically use this task to do the actual processing of data.</font> - <font color=red>// Note the use of Thru_Task. Since a module must always have a</font> - <font color=red>// pair of tasks we use this on the writer side as a no-op.</font> - if (reader) - { - if (stream ().push (new Module ("<font color=green>Reader</font>", - new Thru_Task (), - reader)) == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "<font color=green>%p\n</font>", - "<font color=green>stream().push(reader)</font>"), - -1); - } - - return 0; -} - -<font color=red>/* Add the necessary protocol objects to the stream. The way we're - pushing things on we will encrypt the data before compressing it. -*/</font> -int -<font color=#008888>Protocol_Stream::open</font> (void) -{ -<font color=blue>#if defined</font> (<font color=purple>ENABLE_COMPRESSION</font>) - if (stream ().push (new Module ("<font color=green>compress</font>", - new Compressor (), - new Compressor ())) == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "<font color=green>%p\n</font>", - "<font color=green>stream().push(comprssor)</font>"), - -1); -<font color=blue>#endif</font> <font color=red>/* ENABLE_COMPRESSION */</font> - -<font color=blue>#if defined</font> (<font color=purple>ENABLE_ENCRYPTION</font>) - if (stream ().push (new Module ("<font color=green>crypt</font>", - new Crypt (), - new Crypt ())) == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "<font color=green>%p\n</font>", - "<font color=green>stream().push(crypt)</font>"), - -1); -<font color=blue>#endif</font> <font color=red>/* ENABLE_ENCRYPTION */</font> - return 0; -} - -<font color=red>// Closing the Protocol_Stream is as simple as closing the ACE_Stream.</font> -int -<font color=#008888>Protocol_Stream::close</font> (void) -{ - return stream ().close (); -} - -<font color=red>// Simply pass the data directly to the ACE_Stream.</font> -int -<font color=#008888>Protocol_Stream::put</font> (ACE_Message_Block *&message, - ACE_Time_Value *timeout) -{ - return stream ().put (message, - timeout); -} - -<font color=red>/* Tell the Recv module to read some data from the peer and pass it - upstream. Servers will typically use this method in a - handle_input() method to tell the stream to get a client's request. */</font> - -int -<font color=#008888>Protocol_Stream::get</font>(void) -{ - <font color=red>// If there is no Recv module, we're in big trouble!</font> - if (recv_ == 0) - ACE_ERROR_RETURN ((LM_ERROR, - "<font color=green>(%P|%t) No Recv object!\n</font>"), - -1); - - <font color=red>// This tells the Recv module to go to it's peer() and read some</font> - <font color=red>// data. Once read, that data will be pushed upstream. If there is</font> - <font color=red>// a reader object then it will have a chance to process the data.</font> - <font color=red>// If not, the received data will be available in the message queue</font> - <font color=red>// of the stream head's reader object (eg --</font> - <font color=red>// stream().head()->reader()->msg_queue()) and can be read with our</font> - <font color=red>// other get() method below.</font> - if (recv_->get () == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "<font color=green>(%P|%t) Cannot queue read request\n</font>"), - -1); - - <font color=red>// For flexibility I've added an error() method to tell us if</font> - <font color=red>// something bad has happened to the Recv object.</font> - if (recv_->error ()) - ACE_ERROR_RETURN ((LM_ERROR, - "<font color=green>(%P|%t) Recv object error!\n</font>"), - -1); - - return 0; -} - -<font color=red>/* Take a message block off of the stream head reader's message queue. - If the queue is empty, use get() to read from the peer. This is - most often used by client applications. Servers will generaly - insert a reader that will prevent the data from getting all the way - upstream to the head. */</font> -int -<font color=#008888>Protocol_Stream::get</font> (ACE_Message_Block *&response, - ACE_Time_Value *timeout ) -{ - if (stream ().head ()->reader ()->msg_queue ()->is_empty () - && this->get () == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "<font color=green>(%P|%t) Cannot get data into the stream.\n</font>"), - -1); - - return stream ().head ()->reader ()->getq (response, - timeout); -} -</PRE> -<P><HR WIDTH="100%"> -<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] [<A HREF="page12.html">Continue This Tutorial</A>]</CENTER> diff --git a/docs/tutorials/015/page12.html b/docs/tutorials/015/page12.html deleted file mode 100644 index 93358494a85..00000000000 --- a/docs/tutorials/015/page12.html +++ /dev/null @@ -1,80 +0,0 @@ -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 015</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 015</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Building a protocol stream</FONT></B></CENTER> - -<P> -<HR WIDTH="100%"> -A quick look at the Protocol_Task header... -<HR> -<PRE> -<font color=red>// $Id$</font> - -<font color=blue>#ifndef</font> <font color=purple>PROTOCOL_TASK_H</font> -<font color=blue>#define</font> <font color=purple>PROTOCOL_TASK_H</font> - -<font color=blue>#include</font> "<A HREF="../../../ace/Task.h">ace/Task.h</A>" - -<font color=blue>#if !defined</font> (<font color=purple>ACE_LACKS_PRAGMA_ONCE</font>) -<font color=blue># pragma</font> <font color=purple>once</font> -<font color=blue>#endif</font> <font color=red>/* ACE_LACKS_PRAGMA_ONCE */</font> - -<font color=red>/* A typical ACE_Task<> derivative that adds a few things appropriate - to protocol stacks. To keep things a little simpler, we prevent - activation of the task and just borrow the thread of control from - the calling method in all cases. -*/</font> -class Protocol_Task : public ACE_Task<ACE_MT_SYNCH> -{ -public: - typedef ACE_Task<ACE_MT_SYNCH> inherited; - - Protocol_Task (void); - - ~Protocol_Task (void); - - <font color=red>// open() is invoked when the task is inserted into the stream.</font> - virtual int open (void *arg); - - <font color=red>// close() is invoked when the stream is closed (flags will be set</font> - <font color=red>// to '1') and when the svc() method exits (flags will be '0').</font> - virtual int close (u_long flags); - - <font color=red>// As data travels through the stream, the put() method of each task</font> - <font color=red>// is invoked to keep the data moving along.</font> - virtual int put (ACE_Message_Block *message, - ACE_Time_Value *timeout); - - <font color=red>// We're obligated to provide this signature even though we won't be </font> - <font color=red>// allowing this object to be activated.</font> - virtual int svc (void); - -protected: - - <font color=red>// Called by put() or svc() as necessary to process a block of data.</font> - int process (ACE_Message_Block *message, - ACE_Time_Value *timeout); - - <font color=red>// Tasks on the writer (downstream) side of the stream are called</font> - <font color=red>// upon to send() data that will ultimately go to the peer.</font> - virtual int send (ACE_Message_Block *message, - ACE_Time_Value *timeout); - - <font color=red>// Tasks on the reader (upstream) side will be receiving data that</font> - <font color=red>// came from the peer.</font> - virtual int recv (ACE_Message_Block *message, - ACE_Time_Value *timeout); - -}; - -<font color=blue>#endif</font> <font color=red>/* PROTOCOL_TASK_H */</font> -</PRE> -<P><HR WIDTH="100%"> -<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] [<A HREF="page13.html">Continue This Tutorial</A>]</CENTER> diff --git a/docs/tutorials/015/page13.html b/docs/tutorials/015/page13.html deleted file mode 100644 index a6371dcc60a..00000000000 --- a/docs/tutorials/015/page13.html +++ /dev/null @@ -1,97 +0,0 @@ -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 015</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 015</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Building a protocol stream</FONT></B></CENTER> - -<P> -<HR WIDTH="100%"> -The Protocol_Task implementation takes care of the open(), close(), -put() and svc() methods so that derivatives can concentrate on the -send() and recv() methods. After a while you find that most -ACE_Task<> derivatives look very similar in the four basic methods and -only need one or two additional to do any real work. -<HR> -<PRE> - -<font color=red>// $Id$</font> - -<font color=blue>#include</font> "<font color=green>Protocol_Task.h</font>" - -<font color=red>// Construct the object and remember the thread count.</font> -<font color=#008888>Protocol_Task::Protocol_Task</font>(void) -{ - ; -} - -<font color=#008888>Protocol_Task::~Protocol_Task</font>(void) -{ - ; -} - -int <font color=#008888>Protocol_Task::open</font>(void *arg) -{ - ACE_UNUSED_ARG(arg); - - return(0); -} - -int <font color=#008888>Protocol_Task::close</font>(u_long flags) -{ - return 0; -} - -<font color=red>/* When a message is put() onto the task, it's time to process() some data. -*/</font> -int <font color=#008888>Protocol_Task::put</font>(ACE_Message_Block *message,ACE_Time_Value *timeout) -{ - return this->process(message,timeout); -} - -<font color=red>/* Return an error since we don't want the task to ever be activated. - */</font> -int <font color=#008888>Protocol_Task::svc</font>(void) -{ - return -1; -} - -<font color=red>/* There's nothing really magic about process(). We just decide if - we're moving data upstream or downstream and invoke the appropriate - virtual function to handle it. -*/</font> -int <font color=#008888>Protocol_Task::process</font>(ACE_Message_Block * message, ACE_Time_Value *timeout) -{ - if( this->is_writer() ) - { - return this->send(message,timeout); - } - - return this->recv(message,timeout); -} - -<font color=red>/* We must insist that derivatives provide a meaningful overload for - these methods. It's fairly common for ACE object methods to return - an error when an overload is expected but the method cannot be - safely made pure virtual. - */</font> - -int <font color=#008888>Protocol_Task::send</font>(ACE_Message_Block *message, - ACE_Time_Value *timeout) -{ - return -1; -} - -int <font color=#008888>Protocol_Task::recv</font>(ACE_Message_Block * message, - ACE_Time_Value *timeout) -{ - return -1; -} -</PRE> -<P><HR WIDTH="100%"> -<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] [<A HREF="page14.html">Continue This Tutorial</A>]</CENTER> diff --git a/docs/tutorials/015/page14.html b/docs/tutorials/015/page14.html deleted file mode 100644 index ea27af4db50..00000000000 --- a/docs/tutorials/015/page14.html +++ /dev/null @@ -1,74 +0,0 @@ -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 015</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 015</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Building a protocol stream</FONT></B></CENTER> - -<P> -<HR WIDTH="100%"> -The Xmit object knows how to send data to the peer. It sits at the -tail of the stream and gets everything that flows down from the head. -In keeping with the spirit of things, this object does only one thing -and doesn't concern itself with anyone else' details. -<P> -The only thing you might want to do is combine it with Recv. Why? -As you'll realize in a page or two, the Xmit and Recv objects must -interact if you're going to ensure a safe transit. By having a single -object it's easier to coordinate and maintain the interaction. -<HR> -<PRE> -<font color=red>// $Id$</font> - -<font color=blue>#ifndef</font> <font color=purple>XMIT_H</font> -<font color=blue>#define</font> <font color=purple>XMIT_h</font> - -<font color=blue>#include</font> "<font color=green>Protocol_Task.h</font>" - -<font color=red>// Forward reference reduces <font color=blue>#include</font> dependencies</font> -class ACE_SOCK_Stream; - -<font color=red>/* A class suitable for sending data to a peer from within an - ACE_Stream. - */</font> -class Xmit : public Protocol_Task -{ -public: - typedef Protocol_Task inherited; - - <font color=red>// We must be given a valid peer when constructed. Without that we</font> - <font color=red>// don't know who to send data to.</font> - Xmit (ACE_SOCK_Stream &peer); - ~Xmit (void); - - <font color=red>// As you know, close() will be called in a couple of ways by the</font> - <font color=red>// ACE framework. We use that opportunity to terminate the</font> - <font color=red>// connection to the peer.</font> - int close (u_long flags); - -protected: - - ACE_SOCK_Stream &peer (void) - { - return this->peer_; - } - - <font color=red>// Send the data to the peer. By now it will have been completely</font> - <font color=red>// protocol-ized by other tasks in the stream.</font> - int send (ACE_Message_Block *message, - ACE_Time_Value *timeout); - -private: - <font color=red>// A representation of the peer we're talking to.</font> - ACE_SOCK_Stream &peer_; -}; - -<font color=blue>#endif</font> <font color=red>/* XMIT_H */</font> -</PRE> -<P><HR WIDTH="100%"> -<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] [<A HREF="page15.html">Continue This Tutorial</A>]</CENTER> diff --git a/docs/tutorials/015/page15.html b/docs/tutorials/015/page15.html deleted file mode 100644 index 66e4f1bf852..00000000000 --- a/docs/tutorials/015/page15.html +++ /dev/null @@ -1,118 +0,0 @@ -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 015</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 015</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Building a protocol stream</FONT></B></CENTER> - -<P> -<HR WIDTH="100%"> -The implementation of Xmit isn't too complicated. If we choose to -combine it with the Recv task we simply lift the recv() method from -that object and drop it into this one. -<P> -Note that close() must decide if it's being called when the stream is -shutdown or when it's svc() method exits. Since we tell the baseclass -not to use any threads it's a safe bet that flags will always be -non-zero. Still, it's good practice to plan for the future by -checking the value. -<P> -Note also that when we send the data we prefix it with the data size. -This let's our sibling Recv ensure that an entire block is received -together. This can be very important for compression and encryption -processes which typically work better with blocks of data instead of -streams of data. -<HR> -<PRE> - -<font color=red>// $Id$</font> - -<font color=blue>#include</font> "<font color=green>Xmit.h</font>" -<font color=blue>#include</font> "<A HREF="../../../ace/SOCK_Stream.h">ace/SOCK_Stream.h</A>" - -<font color=red>/* Construct the object with the peer connection and choose not to - activate ourselves into a dedicated thread. You might get some - performance gain by activating but if you really want a - multi-threaded apprroach you should handle that as a separate - issue. Attempting to force threading at this level will likely - cause more trouble than you want to deal with. -*/</font> -<font color=#008888>Xmit::Xmit</font>( ACE_SOCK_Stream & _peer ) - : Protocol_Task(), peer_(_peer) -{ -} - -<font color=#008888>Xmit::~Xmit</font>(void) -{ -} - -<font color=red>/* Check to see if we're being closed by the stream (flags != 0) or if - we're responding to the exit of our svc() method. -*/</font> -int <font color=#008888>Xmit::close</font>(u_long flags) -{ - <font color=red>// Take care of the baseclass closure.</font> - int rval = <font color=#008888>inherited::close</font>(flags); - - <font color=red>// Only if we're being called at the stream shutdown do we close</font> - <font color=red>// the peer connection. If, for some reason, we were activated</font> - <font color=red>// into one or more threads we wouldn't want to close the pipe</font> - <font color=red>// before all threads had a chance to flush their data.</font> - if( flags ) - { - peer().close(); - } - - return( rval ); -} - -<font color=red>/* Our overload of send() will take care of sending the data to the - peer. -*/</font> -int <font color=#008888>Xmit::send</font>(ACE_Message_Block *message, ACE_Time_Value *timeout) -{ - int rval; - - ACE_DEBUG ((LM_INFO, "<font color=green>(%P|%t) <font color=#008888>Xmit::send</font>() sending (%s)(%d)\n</font>", message->rd_ptr(), message->length() )); - - <font color=red>/* Since we're going to be sending data that may have been - compressed and encrypted it's probably important for the - receiver to get an entire "<font color=green>block</font>" instead of having a - partial read. - - For that reason, we'll send the length of the message block - (in clear-text) to the peer so that it can then recv_n() - the entire block contents in one read operation. - */</font> - char msize[32]; - sprintf(msize,"<font color=green>%d</font>",message->length()); - - <font color=red>// Be sure we send the end-of-string NULL so that Recv will</font> - <font color=red>// know when to stop assembling the length.</font> - rval = this->peer().send_n( msize, strlen(msize)+1, 0, timeout ); - - if( rval == -1 ) - { - ACE_ERROR_RETURN ((LM_ERROR, "<font color=green>%p\n</font>", "<font color=green><font color=#008888>Xmit::send</font>() Failed to send message size.</font>"), -1); - } - - <font color=red>/* Now we send the actual data. If you're worried about - network efficiency then you may choose to create one buffer - containing msize and the message data and send it all at - once. - */</font> - rval = this->peer().send_n( message->rd_ptr(), message->length(), 0, timeout ); - - <font color=red>// Release the message block since we're done with it.</font> - message->release(); - - return( rval ); -} -</PRE> -<P><HR WIDTH="100%"> -<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] [<A HREF="page16.html">Continue This Tutorial</A>]</CENTER> diff --git a/docs/tutorials/015/page16.html b/docs/tutorials/015/page16.html deleted file mode 100644 index e372f6d68bf..00000000000 --- a/docs/tutorials/015/page16.html +++ /dev/null @@ -1,89 +0,0 @@ -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 015</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 015</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Building a protocol stream</FONT></B></CENTER> - -<P> -<HR WIDTH="100%"> -Recv is the sibling to Xmit. Again, they could be combined into a -single object if you want. -<P> -An ACE_Stream is designed to handle downstream traffic very -well. You put() data into it and it flows along towards the tail. -However, there doesn't seem to be a way to put data in such that it -will travel upstream. To get around that, I've added a get() method -to Recv that will trigger a read on the socket. Recv will then put -the data to the next upstream module and we're on our way. As noted -earlier, that data will eventually show up either in the <i>reader</i> -(if installed on the stream open()) or the stream head reader task's -message queue. -<HR> -<PRE> -<font color=red>// $Id$</font> - -<font color=blue>#ifndef</font> <font color=purple>RECV_H</font> -<font color=blue>#define</font> <font color=purple>RECV_h</font> - -<font color=blue>#include</font> "<font color=green>Protocol_Task.h</font>" - -class ACE_SOCK_Stream; - -<font color=red>/* Get some data from the peer and send it upstream for - de-protocol-ization. -*/</font> -class Recv : public Protocol_Task -{ -public: - typedef Protocol_Task inherited; - - <font color=red>// Give it someone to talk to...</font> - Recv (ACE_SOCK_Stream &peer); - ~Recv (void); - - <font color=red>// Trigger a read from the socket</font> - int get (void); - - <font color=red>// In some cases it might be easier to check the "<font color=green>state</font>" of the Recv</font> - <font color=red>// object than to rely on return codes filtering back to you.</font> - int error (void) - { - return this->error_; - } - -protected: - - ACE_SOCK_Stream &peer (void) - { - return this->peer_; - } - - <font color=red>// The baseclass will trigger this when our get() method is called.</font> - <font color=red>// A message block of the appropriate size is created, filled and</font> - <font color=red>// passed up the stream.</font> - int recv (ACE_Message_Block *message, - ACE_Time_Value *timeout = 0); - -private: - <font color=red>// Our endpoint</font> - ACE_SOCK_Stream &peer_; - - <font color=red>// get() uses a bogus message block to cause the baseclass to invoke</font> - <font color=red>// recv(). To avoid memory thrashing, we create that bogus message</font> - <font color=red>// once and reuse it for the life of Recv.</font> - ACE_Message_Block *tickler_; - - <font color=red>// Our error flag (duh)</font> - int error_; -}; - -<font color=blue>#endif</font> <font color=red>/* RECV_H */</font> -</PRE> -<P><HR WIDTH="100%"> -<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] [<A HREF="page17.html">Continue This Tutorial</A>]</CENTER> diff --git a/docs/tutorials/015/page17.html b/docs/tutorials/015/page17.html deleted file mode 100644 index 3a07c2eca89..00000000000 --- a/docs/tutorials/015/page17.html +++ /dev/null @@ -1,116 +0,0 @@ -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 015</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 015</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Building a protocol stream</FONT></B></CENTER> - -<P> -<HR WIDTH="100%"> -The Recv implementation is nearly as simple as Xmit. There's -opportunity for error when we get the message size and we have to -manage the lifetime of the tickler but other than that it's pretty -basic stuff. -<HR> -<PRE> - -<font color=red>// $Id$</font> - -<font color=blue>#include</font> "<font color=green>Recv.h</font>" -<font color=blue>#include</font> "<A HREF="../../../ace/SOCK_Stream.h">ace/SOCK_Stream.h</A>" - -<font color=red>/* Construct the object with the peer reference and other appropriate - initializations. -*/</font> -<font color=#008888>Recv::Recv</font>( ACE_SOCK_Stream & _peer ) - : Protocol_Task(), peer_(_peer), error_(0) -{ - <font color=red>// Create the tickler that get() will use to trigger recv()</font> - <font color=red>// through the baseclass. Since we're single-threaded this is</font> - <font color=red>// probably overkill but it makes multi-threading easier if we</font> - <font color=red>// choose to do that.</font> - tickler_ = new ACE_Message_Block(1); -} - -<font color=red>/* Be sure we manage the lifetime of the tickler to prevent a memory - leak. -*/</font> -<font color=#008888>Recv::~Recv</font>(void) -{ - tickler_->release(); -} - -<font color=red>/* By putting the tickler to ourselves we cause things to happen in - the baseclass that will invoke recv(). If we know we're single - threaded we could directly call recv() and be done with it but then - we'd have to do something else if we're multi-threaded. Just let - the baseclass worry about those things! -*/</font> -int <font color=#008888>Recv::get</font>(void) -{ - return this->put( tickler_, 0 ); -} - -int <font color=#008888>Recv::recv</font>(ACE_Message_Block * message, ACE_Time_Value *timeout) -{ - int rval; - - <font color=red>/* Xmit will send us the message length in clear-text. I - assume that will be less than 32-bytes! - */</font> - char msize[32]; - int b = 0; - - <font color=red>/* Read from the socket one byte at a time until we see then - end-of-string NULL character. Since the OS layers (at least - in Unix) will provide some buffering this isn't as bad as - it may seem at first. - - The byte-at-a-time recv breaks horribly on Win32 where the - WFMO_Reactor is used. This is because the socket has been - placed into non-blocking mode and only the recv() of the - first byte will block. The solution is to use - ACE_Select_Reactor which doesn't change the socket - characteristics. We did that back in main(), so we should - be in good shape now. - */</font> - do - { - rval = this->peer().recv( &msize[b], 1, timeout ); - if( rval == -1 ) - { - error_ = 1; - ACE_ERROR_RETURN ((LM_ERROR, "<font color=green>%p\n</font>", "<font color=green><font color=#008888>Recv::recv</font>() Failed to get message size.</font>"), -1); - } - } - while( msize[b++] != 0 ); - - int size = <font color=#008888>ACE_OS::atoi</font>(msize); - - <font color=red>// Make a block big enough to contain the data we'll read</font> - message = new ACE_Message_Block( size ); - - <font color=red>// Read the actual message data into our new message block</font> - rval = this->peer().recv_n( message->wr_ptr(), size, 0, timeout ); - - <font color=red>// If we got the data correctly then send it on upstream.</font> - if( rval > 0 ) - { - message->wr_ptr( rval ); - return( this->put_next( message ) ); - } - - <font color=red>// Something bad happend on the recv_n(). Set an error flag</font> - <font color=red>// and return error.</font> - error_ = 1; - - return( -1 ); -} -</PRE> -<P><HR WIDTH="100%"> -<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] [<A HREF="page18.html">Continue This Tutorial</A>]</CENTER> diff --git a/docs/tutorials/015/page18.html b/docs/tutorials/015/page18.html deleted file mode 100644 index d17427ffeeb..00000000000 --- a/docs/tutorials/015/page18.html +++ /dev/null @@ -1,60 +0,0 @@ -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 015</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 015</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Building a protocol stream</FONT></B></CENTER> - -<P> -<HR WIDTH="100%"> -This and the next three pages present the protocol objects that -provide compression and encryption. If you were hoping to learn the -secrets of compression and encryption then I'm going to disappoint -you. There are some really good libraries out there that do this -stuff though and if anyone wants to integrate one of them into the -tutorial I'll be glad to take it! -<HR> -<PRE> -<font color=red>// $Id$</font> - -<font color=blue>#ifndef</font> <font color=purple>COMPRESSOR_H</font> -<font color=blue>#define</font> <font color=purple>COMPRESSOR_h</font> - -<font color=blue>#include</font> "<font color=green>Protocol_Task.h</font>" - -<font color=red>/* A reallly dumb compression object. (It actually adds 3 bytes to - every message block.) -*/</font> -class Compressor : public Protocol_Task -{ -public: - - typedef Protocol_Task inherited; - - Compressor (void); - - ~Compressor (void); - -protected: - - <font color=red>// This is called when the compressor is on the downstream side.</font> - <font color=red>// We'll take the message, compress it and move it along to the next</font> - <font color=red>// module.</font> - int send (ACE_Message_Block *message, - ACE_Time_Value *timeout); - - <font color=red>// This one is called on the upstream side. No surprise: we</font> - <font color=red>// decompress the data and send it on up the stream.</font> - int recv (ACE_Message_Block *message, - ACE_Time_Value *timeout); -}; - -<font color=blue>#endif</font> <font color=red>/* COMPRESSOR_H */</font> -</PRE> -<P><HR WIDTH="100%"> -<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] [<A HREF="page19.html">Continue This Tutorial</A>]</CENTER> diff --git a/docs/tutorials/015/page19.html b/docs/tutorials/015/page19.html deleted file mode 100644 index 2b62ec0bdb3..00000000000 --- a/docs/tutorials/015/page19.html +++ /dev/null @@ -1,116 +0,0 @@ -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 015</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 015</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Building a protocol stream</FONT></B></CENTER> - -<P> -<HR WIDTH="100%"> -Here we implement the details of our compression. By having both -compression and decompression in one object it's easier to keep track -of implementation details. Splitting Xmit/Recv like I did will make -things more difficult if something has to change in their interaction. -<HR> -<PRE> - -<font color=red>// $Id$</font> - -<font color=blue>#include</font> "<font color=green>Compressor.h</font>" -<font color=blue>#include</font> "<A HREF="../../../ace/SOCK_Stream.h">ace/SOCK_Stream.h</A>" - -<font color=#008888>Compressor::Compressor</font>( void ) - : Protocol_Task() -{ - ; -} - -<font color=#008888>Compressor::~Compressor</font>(void) -{ - ; -} - -<font color=red>/* This is where you insert your compression code. Most compressors - want to work on a block of data instead of a byte-stream. - Fortunately the message block has a block that can be compressed. - Take a look at libz for a quick way to add compression to your - apps - */</font> -int <font color=#008888>Compressor::send</font>(ACE_Message_Block *message, ACE_Time_Value *timeout) -{ - ACE_DEBUG ((LM_INFO, "<font color=green>(%P|%t) <font color=#008888>Compressor::send</font>() compressing (%s)\n</font>", message->rd_ptr() )); - - <font color=red>// Create a block to hold the compressed data. I belive libz</font> - <font color=red>// recommends a buffer about 10-20% larger than the source.</font> - <font color=red>// Other libraries/algorithms may have their own quirks.</font> - ACE_Message_Block * compressed = new ACE_Message_Block( message->size() ); - - <font color=red>// Perform a bogus compression algorithm. 'CD' just tells me</font> - <font color=red>// that this is compressed data and when we "<font color=green>decompress</font>" we'll </font> - <font color=red>// look for this signature to validate the data received.</font> - <font color=#008888>ACE_OS::sprintf</font>( compressed->wr_ptr(), "<font color=green>CD:%s</font>", message->rd_ptr() ); - compressed->wr_ptr( strlen(compressed->wr_ptr())+1 ); - - <font color=red>// Send the compressed data down the stream to the next module</font> - this->put_next( compressed ); - - <font color=red>// We're done here.</font> - message->release(); - - return( 0 ); -} - -<font color=red>/* And here's the decompression side. We've written Xmit/Recv so that - we're guaranteed to get an entire block of compressed data. If - we'd used recv() in the Recv object then we might have gotten a - partial block and that may not decompress very nicely. - */</font> -int <font color=#008888>Compressor::recv</font>(ACE_Message_Block *message, ACE_Time_Value *timeout) -{ - ACE_DEBUG ((LM_INFO, "<font color=green>(%P|%t) <font color=#008888>Compress::recv</font>() decompressing (%s)\n</font>", message->rd_ptr() )); - - <font color=red>// Room for the decompressed data. In the real world you</font> - <font color=red>// would probably want to send the original (uncompressed)</font> - <font color=red>// data size in the message. You can predict the maximum</font> - <font color=red>// possible decompression size but it's cheap and easy just to </font> - <font color=red>// send that along. Look again at how I do exacly that</font> - <font color=red>// between Xmit and Recv.</font> - ACE_Message_Block * decompressed = new ACE_Message_Block( message->size() ); - - <font color=red>// Check for our signature. Even when you use a real</font> - <font color=red>// compression algorithm you may want to include your own</font> - <font color=red>// signature so that you can verify the block. It pays to be</font> - <font color=red>// paranoid!</font> - if( <font color=#008888>ACE_OS::strncmp</font>( message->rd_ptr(), "<font color=green>CD:</font>", 3 ) ) - { - ACE_DEBUG ((LM_INFO, "<font color=green>(%P|%t) Improperly encompressed data.\n</font>" )); - message->release(); - return(-1); - } - - <font color=red>// Skip past the signature before going any further.</font> - message->rd_ptr( 3 ); - - <font color=red>// Perform a bogus decompression algorithm. This is where you </font> - <font color=red>// would feed to libz or your favorite decompressor. (It's</font> - <font color=red>// costly but you could invoke popen() on gzip!)</font> - <font color=#008888>ACE_OS::sprintf</font>( decompressed->wr_ptr(), "<font color=green>%s</font>", message->rd_ptr() ); - decompressed->wr_ptr( strlen(decompressed->wr_ptr())+1 ); - - <font color=red>// Recv the decompressed data down the stream to the next module</font> - this->put_next( decompressed ); - - <font color=red>// We're done here.</font> - message->release(); - - return( 0 ); -} - -</PRE> -<P><HR WIDTH="100%"> -<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] [<A HREF="page20.html">Continue This Tutorial</A>]</CENTER> diff --git a/docs/tutorials/015/page20.html b/docs/tutorials/015/page20.html deleted file mode 100644 index 5a073600d10..00000000000 --- a/docs/tutorials/015/page20.html +++ /dev/null @@ -1,58 +0,0 @@ -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 015</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 015</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Building a protocol stream</FONT></B></CENTER> - -<P> -<HR WIDTH="100%"> -While I might be able to come up with a competitive compressor, I -don't have a snowball's chance to code up encryption. I'd be better -off piping the data through the standard Unix crypt command. -<P> -So, while I was lazy with Compress, I'm realistic with Crypt. I'll -show you the hooks and entry points and let someone else contribute an -encryptor. -<HR> -<PRE> -<font color=red>// $Id$</font> - -<font color=blue>#ifndef</font> <font color=purple>CRYPT_H</font> -<font color=blue>#define</font> <font color=purple>CRYPT_h</font> - -<font color=blue>#include</font> "<font color=green>Protocol_Task.h</font>" - -<font color=red>/* An interface (adaptor) between your favorite encryption method and - an ACE_Stream. -*/</font> -class Crypt : public Protocol_Task -{ -public: - - typedef Protocol_Task inherited; - - Crypt (void); - - ~Crypt (void); - -protected: - - <font color=red>// Moving downstream will encrypt the data</font> - int send (ACE_Message_Block *message, - ACE_Time_Value *timeout); - - <font color=red>// And moving upstream will decrypt it.</font> - int recv (ACE_Message_Block *message, - ACE_Time_Value *timeout); -}; - -<font color=blue>#endif</font> <font color=red>/* CRYPT_H */</font> -</PRE> -<P><HR WIDTH="100%"> -<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] [<A HREF="page21.html">Continue This Tutorial</A>]</CENTER> diff --git a/docs/tutorials/015/page21.html b/docs/tutorials/015/page21.html deleted file mode 100644 index a1aced14565..00000000000 --- a/docs/tutorials/015/page21.html +++ /dev/null @@ -1,99 +0,0 @@ -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 015</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 015</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Building a protocol stream</FONT></B></CENTER> - -<P> -<HR WIDTH="100%"> -The encryption implementation isn't any smarter than that of the -compressor. Still, the hooks are there for you to insert your -favorite library. -<HR> -<PRE> - -<font color=red>// $Id$</font> - -<font color=blue>#include</font> "<font color=green>Crypt.h</font>" -<font color=blue>#include</font> "<A HREF="../../../ace/SOCK_Stream.h">ace/SOCK_Stream.h</A>" - -<font color=red>/* The expected constructor... - */</font> -<font color=#008888>Crypt::Crypt</font>( void ) - : Protocol_Task() -{ -} - -<font color=#008888>Crypt::~Crypt</font>(void) -{ -} - -<font color=red>/* To send the data we'll apply a signature and encryption. - */</font> -int <font color=#008888>Crypt::send</font>(ACE_Message_Block *message, ACE_Time_Value *timeout) -{ - ACE_DEBUG ((LM_INFO, "<font color=green>(%P|%t) <font color=#008888>Crypt::send</font>() encrypting (%s)\n</font>", message->rd_ptr() )); - - <font color=red>// I suspect that some encryptors might change the data size.</font> - <font color=red>// It probably isn't safe to create a same-size destination buffer.</font> - ACE_Message_Block * encrypted = new ACE_Message_Block( message->size() ); - - <font color=red>// Perform a bogus encryption algorithm and add our safety</font> - <font color=red>// signature. Adding the original data size is also probably</font> - <font color=red>// a good idea that I haven't encorporated here.</font> - <font color=#008888>ACE_OS::sprintf</font>( encrypted->wr_ptr(), "<font color=green>ED:%s</font>", message->rd_ptr() ); - encrypted->wr_ptr( strlen(encrypted->wr_ptr())+1 ); - - <font color=red>// Send the encrypted data down the stream to the next module</font> - this->put_next( encrypted ); - - <font color=red>// We're done here.</font> - message->release(); - - return( 0 ); -} - -<font color=red>/* The upstream movement requires that we decrypt what the peer has - given us. -*/</font> -int <font color=#008888>Crypt::recv</font>(ACE_Message_Block *message, ACE_Time_Value *timeout) -{ - ACE_DEBUG ((LM_INFO, "<font color=green>(%P|%t) <font color=#008888>Crypt::recv</font>() decrypting (%s)\n</font>", message->rd_ptr() )); - - <font color=red>// Create a destination for the decrypted data. The same</font> - <font color=red>// block size caveat exists of course.</font> - ACE_Message_Block * decrypted = new ACE_Message_Block( message->size() ); - - <font color=red>// Check the signature as expected.</font> - if( <font color=#008888>ACE_OS::strncmp</font>( message->rd_ptr(), "<font color=green>ED:</font>", 3 ) ) - { - ACE_DEBUG ((LM_INFO, "<font color=green>(%P|%t) Improperly encrypted data.\n</font>" )); - message->release(); - return(-1); - } - - <font color=red>// Don't forget to skip past the signature before decrypting</font> - <font color=red>// or things will be quite exciting!</font> - message->rd_ptr( 3 ); - - <font color=red>// Perform a bogus decryption algorithm</font> - <font color=#008888>ACE_OS::sprintf</font>( decrypted->wr_ptr(), "<font color=green>%s</font>", message->rd_ptr() ); - decrypted->wr_ptr( strlen(decrypted->wr_ptr())+1 ); - - <font color=red>// Send the decrypted data down the stream to the next module</font> - this->put_next( decrypted ); - - <font color=red>// We're done here.</font> - message->release(); - - return( 0 ); -} -</PRE> -<P><HR WIDTH="100%"> -<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] [<A HREF="page22.html">Continue This Tutorial</A>]</CENTER> diff --git a/docs/tutorials/015/page22.html b/docs/tutorials/015/page22.html deleted file mode 100644 index 2c412e41b30..00000000000 --- a/docs/tutorials/015/page22.html +++ /dev/null @@ -1,82 +0,0 @@ -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 015</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 015</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Building a protocol stream</FONT></B></CENTER> - -<P> -<HR WIDTH="100%"> -Well, this has certainly been one of the more verbose tutorials to -date. I must say "thanks" to everyone who stuck it out this far! -<P> -A quick review of what we've done: -<UL> - -<LI>Create a simple client application and Client object that uses a -Protocol Stream without really knowing how they work. The app (and -object) rely on the public interface of the Protocol Stream to get the -job done. At this level the protocol details are irrelevant. -<P> -<LI>Next, we create a simple server application and Server object -similar to the client. The Protocol Stream is of course used and we -have to know a little more so that we can insert a <i>reader</i> that -will ultimately process the data from the client. -<P> -<LI>We then go into the details of the Protocol_Stream implementation -and it's Protocol_Task object that forms the basis for the stream -tasks. Each object is kept as small and simple as possible to improve -reusability and future maintenance. -<P> -<LI>Finally, the individual protocol objects are discused. Separate -objects for the peer interface were created as well as the bogus -compressor and encryptor. The protocol can be extended or modified by -creating new such objects and installing them in the Protocol_Stream's -open() method. - -</UL> -<P> - -It doesn't sound like much but it certainly took a bunch of files to -get there. It's easy to get lost in the details when there's so much -to cover so you're encouraged to go over things a couple of times. -As always, enhancments of the tutorials is welcome! -<P> -Here's the complete file list: -<UL> -<LI><A HREF="client">Makefile</A> -<P> -<LI><A HREF="Makefile.client">client Makefile</A> -<LI><A HREF="client.cpp">client.cpp</A> -<LI><A HREF="Client_i.h">Client_i.h</A> -<LI><A HREF="Client_i.cpp">Client_i.cpp</A> -<P> -<LI><A HREF="Makefile.server">Server Makefile</A> -<LI><A HREF="server.cpp">server.cpp</A> -<LI><A HREF="Server_i.h">Server_i.h</A> -<LI><A HREF="Server_i.cpp">Server_i.cpp</A> -<LI><A HREF="Handler.h">Handler.h</A> -<LI><A HREF="Handler.cpp">Handler.cpp</A> -<P> -<LI><A HREF="Protocol_Stream.cpp">Protocol_Stream.cpp</A> -<LI><A HREF="Protocol_Stream.h">Protocol_Stream.h</A> -<LI><A HREF="Protocol_Task.cpp">Protocol_Task.cpp</A> -<LI><A HREF="Protocol_Task.h">Protocol_Task.h</A> -<P> -<LI><A HREF="Xmit.cpp">Xmit.cpp</A> -<LI><A HREF="Xmit.h">Xmit.h</A> -<LI><A HREF="Recv.cpp">Recv.cpp</A> -<LI><A HREF="Recv.h">Recv.h</A> -<P> -<LI><A HREF="Compressor.cpp">Compressor.cpp</A> -<LI><A HREF="Compressor.h">Compressor.h</A> -<LI><A HREF="Crypt.cpp">Crypt.cpp</A> -<LI><A HREF="Crypt.h">Crypt.h</A> -</UL> -<P><HR WIDTH="100%"> -<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] </CENTER> diff --git a/docs/tutorials/015/server.cpp b/docs/tutorials/015/server.cpp deleted file mode 100644 index 4867833c220..00000000000 --- a/docs/tutorials/015/server.cpp +++ /dev/null @@ -1,68 +0,0 @@ - -// $Id$ - -#include "Server_i.h" -#include "ace/Select_Reactor.h" - -// A signal handler that will close the server object -extern "C" void handler (int) -{ - Server::close(); -} - -int main (int, char **) -{ - /* On Win32, the WFMO reactor is used by default. - Unfortunately, that causes the sockets to be put into - non-blocking mode which will break Recv::recv(). To - prevent that issue, I explicitly use the Select Reactor - instead. I'll talk more about the "problem" in the Recv - comments. - */ - - // First, we create a Select_Reactor that will do the work. - // To keep things simple, I'll create it on the stack. - ACE_Select_Reactor mySelectReactor; - - // Next, we need an ACE_Reactor that is the bridge between the - // code and the real reactor. It is given a pointer to the - // real reactor. - ACE_Reactor myReactor (&mySelectReactor); - - // Finally, we set the singleton instance to use the reactor - // we've created. - ACE_Reactor::instance (&myReactor); - - // The server object that abstracts away all of the difficult parts. - Server server; - - // Attempt to open the server. Like all good ACE-based - // objects, we'll get -1 on failure. - if( server.open() == -1 ) - { - ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "server.open()"), -1); - } - - // Install a signal handler for ^C so that we can exit gracefully - ACE_Sig_Action sa ((ACE_SignalHandler) handler, SIGINT); - - // Run the server's main loop until we're interrupted - if( server.run() == -1 ) - { - ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "server.run()"), -1); - } - - return 0; -} - -/* These explicit instantiations were taken from an earlier tutorial. - Your compiler may require others as well. -*/ -#if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION) -template class ACE_Acceptor <Handler, ACE_SOCK_ACCEPTOR>; -template class ACE_Svc_Handler<ACE_SOCK_STREAM, ACE_NULL_SYNCH>; -#elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA) -#pragma instantiate ACE_Acceptor <Handler, ACE_SOCK_ACCEPTOR> -#pragma instantiate ACE_Svc_Handler<ACE_SOCK_STREAM, ACE_NULL_SYNCH> -#endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */ - diff --git a/docs/tutorials/015/stream.gif b/docs/tutorials/015/stream.gif Binary files differdeleted file mode 100644 index daae2420b74..00000000000 --- a/docs/tutorials/015/stream.gif +++ /dev/null |