19.10 Proxy Monitor

Team-FLY

Make a copy of proxyserver from Section 19.9 and call it proxymonitor . Modify proxymonitor to take an optional command-line argument, pathname , giving the name of a log file. All header traffic and additional information should be dumped to this file in a useful format. Modify processproxy to take an additional parameter, the name of the log file. Do no logging if this additional parameter is NULL . Log the following information.

  1. Client host name and destination host name

  2. Process ID of the process running processproxy

  3. Initial request line from the client to the proxy

  4. Initial request line sent by the proxy to the server

  5. All additional header lines from the client

  6. All additional header lines from the server

  7. The following byte counts

    1. Length of the initial request from the client

    2. Length of the initial request from the proxy

    3. Length of the additional header lines from the client

    4. Length of the additional header lines from the server

    5. Number of additional bytes sent by the server

    6. Number of additional bytes sent by the client

    7. Total number of bytes sent from the client to the proxy

    8. Total number of bytes sent from the proxy to the server

    9. Total number of bytes sent from the server to the proxy

All this information should be stored in a convenient readable format. All header lines should be labeled to indicate their source. Logging must be done atomically so that the log produced by one child running processproxy is not interleaved with another. You can do this by opening the log file with the O_APPEND flag and doing all logging with a single call to write . A simpler way would be to use the atomic logging facility described in Section 4.9. Section D.1 provides the complete code for this facility.

You will not be able to use tunnel for your implementation because sometimes proxymonitor reads lines and sometimes it reads binary content that is not line oriented. After sending the initial request to the host, as in the proxyserver , the client sends line-oriented data that the proxy logs until the client sends a blank line. The client may then send arbitrary data until the connection is closed. The proxymonitor needs to log only the number of bytes of this additional data. Similarly, the server sends line-oriented header information that proxymonitor logs until the server sends a blank line. The server may then send arbitrary data until the connection is closed, but the proxymonitor logs only the number of bytes the server sent for this portion.

Exercise 19.27

What is wrong with the following strategy for implementing proxymonitor ?

  • Read the initial header line from the client and send the corresponding line to the server (as in the proxyserver ).

  • Read, log and send client header lines until encountering a blank line.

  • Read, log and send server header lines until encountering a blank line.

  • Handle binary data between the client and the server as in tunnel , keeping track of the number of bytes sent in each direction for logging.

Answer:

This should work for GET and HEAD , but it will fail for POST . For a POST command, the client sends its content before the server sends back a header, so the process blocks while waiting for the server header when in fact it should be reading the client content.

One method of implementing proxymonitor is to keep track of the states of the client and server. Each sends headers until a blank line and then sends content. Use select to determine which descriptor is ready and then process either a header line or content, depending on the state of the source. If proxymonitor encounters a blank header line, it changes the state of the respective client or server from header to content.

Exercise 19.28

What happens if several copies of proxymonitor run concurrently using the same log file?

Answer:

As long as the different copies run on different ports, there should not be a problem, provided that logging is atomic. In this case, you might also want to log the port number with each transaction.

Exercise 19.29

Why don't we log the total number of bytes sent from the proxy to the client?

Answer:

This should be the same as the total number of bytes sent from the server to the proxy.

Exercise 19.30

The last three numbers logged are the byte totals for a given transaction. How would you keep track of and log the total number of bytes for each of these items for all transactions processed by proxymonitor ?

Answer:

This requires some work, since the different transactions are handled by different processes. One possibility is to convert the program to use threads rather than children. The total could then be kept in global variables and updated by each thread. The routines to update these totals would have to be protected by a synchronization construct such as a semaphore or a mutex lock.

To do this without using threads, proxymonitor could create an additional child process to keep track of the totals. This process could communicate with the children by running processproxy with two pipes, one to send the new values to this process and one to receive the new totals from this process. Create the two pipes and this child before doing any other processing. The server processes can store the integers in a structure and output them to the pipe in raw form with a single write operation. You need not worry about byte ordering, since the communication is on the same machine. You still need to worry about synchronization to guarantee that the totals received by the children include the values of the current transaction.

Exercise 19.31

Explain the last sentence of the answer to the previous exercise.

Answer:

Suppose we keep track of only one number. The child running processproxy sends the number corresponding to a transaction on one pipe and then reads the new total on the other pipe. Consider the case in which the proxy has just started up and so the current total is 1000. Child A is running a small transaction of 100 bytes, and child B is running a larger transaction of 100,000 bytes. Child A sends 100 on the first pipe and reads the new total on the second pipe. Child B sends 100,000 on the first pipe and reads the new total on the second pipe. If the sending and receiving for each process is not done atomically, The following ordering is possible.

  • Child A sends 100 on the first pipe.

  • 1100 (the new total) is written to the second pipe.

  • Child B sends 100,000 on the first pipe.

  • 101,100 (the new total) is written to the second pipe.

  • Child B reads 1100 from the second pipe.

  • Child A reads 101,100 from the second pipe.

At this pipe, Child B will have completed a transaction of 100,000 bytes and report that the total so far (including this transaction) is 1100 bytes. To fix this problem, make the writing to the first pipe and the reading from the second pipe be atomic. You can do this by using a POSIX:XSI semaphore set shared by all the child processes.

Team-FLY


Unix Systems Programming
UNIX Systems Programming: Communication, Concurrency and Threads
ISBN: 0130424110
EAN: 2147483647
Year: 2003
Pages: 274

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net