// IDL schema definition for Web server interface.
module Web_Server
{
typedef sequence<octet> Chunk_Type;
interface Content_Iterator
{
// This operation returns the next <chunk> of the
// file starting at <offset>. If there are
// no more chunks, false is returned.
boolean next_chunk (in unsigned long offset,
out Chunk_Type chunk);
// This operation destroys the iterator.
void destroy ();
};
exception Error_Result {
// Status of the <get_iterator> operation. These
// values should map onto the normal HTTP
// status values, e.g., 200 means success, 404
// means "file not found," etc.
short status;
};
struct Metadata_Type
{
// Modification date.
string modification_date;
// Type of content.
string content_type;
};
interface Iterator_Factory
{
// This factory method returns a <Content_Iterator> that
// can be used to read the <contents> associated with
// <pathname> one ``chunk'' at a time. The <metadata>
// reports information about the <contents>.
void get_iterator (in string pathname,
out Content_Iterator contents,
out Metadata_Type metadata)
raises (Error_Result);
};
};
The get_iterator is a factory method operation that is
passed an in parameter pathname, which
identifies the content to be downloaded. The
get_iterator operation returns a pair of out
parameters. The first one is a Content_Iterator that can
be used to read the contents identified by the pathname
one ``chunk'' at a time, rather than all at once. The second is a
struct containing metadata that describes
certain information, such as the MIME type and return status, about
the contents. If an error occurs, the
Error_Result exception will be raised, its
status_ field will contain a non-success value, and the
contents parameter will be undefined.
After your client gets a Chunk_Iterator from the Web
server, you will call the next_chunk operation to
retrieve the file one chunk at a time. Each time you call
next_chunk, you'll need to pass in the offset of the file
to read, which keeps the iterator stateless. I recommend reading the
file in BUFSIZ chunks, i.e., the first call to
next_chunk will be with offset 0, the next with offset 0
+ BUFSIZ, etc. Naturally, you'll need to check the length of the
sequence you get back to make sure that you got all the data you
requested.
You will use a CORBA IDL compiler to translate this specification into
client-side stubs and server-side skeletons. The
client application (which you must write) will use the stubs as a
proxy to request the server to download the content. In
addition, you must also write the server, which implements the
get operation that downloads content to the client.
-GI option
of TAO's IDL compiler to generate the skeletons for you.
To implement the get_iterator and next_chunk
operations you'll need to use OS filesystem APIs, such as
open(2), close(2), and read(2).
I recommend that you check the UNIX manual pages for more details on
using these functions.
In addition, you'll need to implement a main function
that defines an instance of Web_Server_i, obtains and
activates the RootPOA and then calls the ORB's run method
to start its event loop.
To make your solution more scalable, the server should
bind its IOR to an instance of the CORBA Naming Service
that you have running. Too keep from interfering with each other's
Naming Services, I recommend you add an entry to your
.cshrc file that assigns your login uid
number to an environment variable called NameServicePort.
Here's how you can do this with csh or tcsh:
setenv NameServicePort 19850
or the following in your .profile file for Bourne shell compatible
shells, e.g., sh, ksh,
Bash:
NameServicePort 19850
export NameServicePort
Note that I got my uid via the id UNIX
command. Remember that valid unprivileged ports on UNIX are greater
than or equal to 1024 (@@ or is 1025) and less than or equal to
65535.
resolve_initial_references to obtain a reference to your
Naming Service (which must be running). This object reference will
then be downcast via _narrow() to an object reference for
a CosNaming::NamingContext interface, which you can then
use to resolve the object reference that the Web server
bound earlier. After you narrow this to the Web_Server
interface, you can call the get_iterator operation via
the object reference to obtain the Chunk_Iterator and use
this to download the file.
next_chunk returns a chunk of the file, write
the contents into a temporary file created in your WWW cache (e.g.,
/tmp/yourloginname) on the local host
[creat,read/write]. Then, spawn an external viewer [fork/exec] to
display the file. You can determine the type of viewer to spawn by
examining the the content_type_ metadata returned by the
server. Once you are done with the files, you might want to remove
them from /tmp/ so that it doesn't fill up!
Back to ECE 255 home page.
Last modified 10:35:50 CST 08 January 2003