Hi,
we are currently implementing a protocol handler (let's say for a schema
"map") somewhat similar to the one for "resource" URIs. For an URI like
"map:foo" the channel (a `mapChannel') looks up "foo" in some table,
where it is mapped to, say, "http://bar.com/". So the mapChannel
constructs an auxiliary channel for "http://bar.com/". This happens in
mapChannel::Init(). Most of the other methods simply call the
corresponding methods of the auxiliary channel.
Exceptions:
- mapChannel::AsyncOpen(...) calls AsyncOpen(...) of the auxiliary
channel, but it passes itself as the listener rather than the
"outside" listener received as an argument. (The outside listener is
remembered in a member variable of the mapChannel.) Thus listener
calls (OnStartRequest, OnStopRequest, OnDataAvailable) from the
auxiliary channel are sent to the mapChannel, which forwards these
calls to the outside listener, however passing itself rather than the
received channel (which would typically be the auxiliary channel).
- mapChannel::GetURI() returns the original URI ("map:foo") rather than
asking the auxiliary channel for its URI ("http://bar.com/").
The modification of AsyncOpen(...) and the implementation of the
listener interface by mapChannel has essentially the purpose to force
the outer listener to ask the mapChannel rather than the auxiliary
channel for its URI.
So far everything is quite standard and we think that we more or less
understand it. It works. Now there is a somewhat more complex situation
for which I would ask for your advice.
Actually the mapping table is not readily available for lookup. We
rather have a socket connection to some "map server". We can write the
original URI ("map:foo" or just "foo") to that socket and tell the
socket's input listener to perform some callback action when the
translated URI arrives from the server.
That is, we have only some sort of "asynchronous" access to the mapping
table and we are not sure how to adapt the implementation of mapChannel
to that.
- One idea is to use threads and event queues to provide a synchronous
interface to the "mapping service" (i.e., a function call returning
the mapped URI rather than a callback).
However, this might be overkill. It might also block important threads
if not done properly. Furthermore, we would have to learn a lot about
threads and event queues. (Is there any up-to-date documentation
available?)
- Another idea is to stick with the callback-style interface of the
mapping service: The mapChannel sends "foo" to the mapping service,
thereby registering a callback that will eventually create the
auxiliary channel.
The problem with this approach is that we do not know how to deal with
method calls to the mapChannel before the auxiliary channel is
available. So we cannot simply forward them to the auxiliary channel.
Well, for certain methods we can do something sensible, but still we
would like to simply forward most method calls in order to make our
layer as transparent as possible.
Fortunately, it looks like many channel methods are not invoked before
a channel has called OnStartRequest(...) at its listener. (After that
time we know that the auxiliary channel exists and we can forward
mapChannel method calls to it.) Can we rely on this? Is there some
(written or implicit) specification that tells when which channel
method may be legally invoked?
Furthermore we have no idea how to implement mapChannel::Open() with
this approach.
Any hints are appreciated,
Heribert.