CSE 532S Interceptor Studio

Please complete the required studio exercises listed below, along with the (optional) enrichment exercises if they interest you.

As you work through the exercises, please record your answers in a file, and upon completion please send an e-mail containing your answers to the cse532@seas.wustl.edu account, with subject line Interceptor Studio.

Please make sure that the name of each person who worked on these exercises is listed at the top of your reply message, and that you number your answers so they are easy for us to match up with the appropriate exercise.

Visual Studio 2013 is not successfully compiling ACE on the Windows machines in Urbauer 218, so you should please use Visual Studio 2012 for this studio (and for subsequent studios and for the lab 3 assignment).

    Required Exercises

  1. Please modify your client and server code from the Acceptor and Connector studio exercises so that a functor is applied (e.g., using the STL transform algorithm) to read and possibly modify the contents of each byte of data passing through the client or server. Initially, this functor should leave the bytes unmodified and should simply pass them through so the program's behavior remains the same even with the interceptor in place (you can think if the interceptor being in an inactive status at that point). Build and test your client and server programs to confirm that the original behavior is preserved. As the answer to this exercise, please describe how you integrated those interceptors into your client and server code.

  2. Extend your interceptors from the previous exercise so that either the client, the server, or both, can be configured with an (admittedly weak) "encryption" functor that performs a reversible operation on each byte. For example, one functor might use modulus arithmetic to add or subtract a value to or from each byte, but have the value wrap back around 0 appropriately if the operation exceeds the upper or lower bound of the value range that the variable can represent. Alternatively, another functor might rotate all the bits of the value by a given number of positions to the right or to the left.

    Configure your client side interceptor to perform one such operation, leaving your server interceptor initially in its original "pass through" configuration. Build and run your code and verify that the data received by the server have been modified by the client interceptor. Then, configure your server interceptor to apply the inverse of the operation that is performed by the client side interceptor. Build and run your code and verify that the data output by the server are the same as the user input. As the answer to this exercise, please show the program input and output for both of these trials, which demonstrate those two different behaviors.

  3. Extend your implementation from the previous exercise so that instead of applying just one functor to each byte, multiple functors can be applied successively to each byte (e.g., according to the GoF Chain of Responsibility design pattern, or via STL functor composition). For example, the client interceptor might modulo-add 17 to each byte and then rotate the bits in it by two positions to the left. The server interceptor might then rotate the bits in each byte by two positions to the right, and then modulo-subtract 17 from that value.

    As in the previous exercise, configure your client to perform such a chain of operations, and run trials with the server in pass-through mode (to demonstrate the client interceptor's modifications) and then applying an inverse-chain to resore the original content that the user typed in. As the answer to this exercise please describe the client and server functors your trials applied, and how you implemented them.

  4. Demonstrate the ability to configure different compatible and incompatible combinations of operations in your client and server interceptors, where compatible means that the server interceptor is able to reverse the modifications made by the client interceptor. Think about various combinations of each kind, such as modulus adding one and then modulus subtracting seven in the client interceptor which would be compatible with simply modulus adding six in the server interceptor. Similarly, some relative permutations of the order in which chains of operations would be applied will be compatible while others will not. Perform several different trials to show these capabilities, and as the answer to this exercise, please describe the trials you ran, what the results were in each case, and show program input and output that demonstrates those behaviors.

    Enrichment Exercises (Optional, based on the Extension Interface pattern)

  5. Modify the interceptor code in your client and server so that a single functor is used for each basic function (e.g., one for rotation, another one for addition/subtraction) but is parameterized with one or more variables that modify the functor's behavior. Each such functor should have appropriate and well defined semantics for how it behaves with each possible value of it's parameter(s). For example, the rotation functor might take an integer that if positive rotates that many positions to the right, if zero does nothing, and if negative rotates a number of positions to the left that is given by the absolute value.

    Using inheritance, delegation, or any other suitable mechanism you would like, provide a common "root" interface from which an interface to each functor can be reached, and which itself can be obtained from the interceptor. As the answer to this exercise, please describe how you implemented your parameterized functors and their interfaces.

  6. Implement a basic user interface (similar to the kind of interface we'll look at in the Component Configurator studio exercises) that lets the user add, remove, and modify parameters of the different functors in each interceptor. Repeat the last of the required exercises using the user interface to configure the interceptors in different ways, and as the answer to this exercise describe how you implemented the user interface and show program input and output documenting its use in different scenarios.