[Openais] Adding a service

Mark Haverkamp markh at osdl.org
Fri Jul 23 15:08:50 PDT 2004


On Fri, 2004-07-23 at 14:57, Steven Dake wrote:
> On Fri, 2004-07-23 at 14:13, Mark Haverkamp wrote:
> > On Mon, 2004-07-19 at 14:00, Steven Dake wrote:
> > 
> > [ ... ]
> > 
> > > 

> 
> This can pose some security risk (since someone could fake a message
> with an invalid handle or somebody else's handle and cause havok).  If
> you can get it to work, though, we can always resolve the problems later
> with a little rework..
> 
> I could be wrong, but I assume you are talking about async events, where
> you must dispatch a message when an async message occurs and at the same
> time be able to handle responses from regular requests on the same fd. 
> There is an API for doing this kind of operation, although a quick look
> through the devmap shows it is not described :(  I would recommend one
> FD for every initialize call since the fd can be used to securely track
> state for a particular user invocation.

Yes, that is pretty much what I want to do.  The single fd sounds a lot
simpler.

> 
> 1. First have a look at exec/amf.c::saAmfInitialize.
> 
> This function creates a queue  to store responses that are not to be
> handled by the syncronous function, but instead meant to be handled by
> the dispatch (async) function.
> 
>     /*
>      * An inq is needed to store async messages while waiting for a
>      * sync response
>      */
>     error = saQueueInit (&amfInstance->inq, 512, sizeof (void *));
>     if (error != SA_OK) {
>         goto error_put_destroy;
>     }
> 
> 2. Next have a look at exec/amf.c::saAmfProtectionGroupTrackStart.
> 
> This function must ensure that it gets a particular response, even when
> it may receive a request for a dispatch (async call).  To solve this,
> the function queues the message on amfInstance->inq.  It will only
> return a message in &req_amf_protectiongrouptrackstart once a message
> with MESSAGE_RES_AMF_PROTECTIONGROUPTRACKSTART defined in header->id of
> the response is received.
> 
>     error = saSendRetry (amfInstance->fd,
> &req_amf_protectiongrouptrackstart,
>         sizeof (struct req_amf_protectiongrouptrackstart),
> MSG_NOSIGNAL);
>     if (error != SA_OK) {
>         goto error_unlock;
>     }
> 
> ^^^^^^ This code sends the request
> 
> 
>     error = saRecvQueue (amfInstance->fd, &message,
>         &amfInstance->inq, MESSAGE_RES_AMF_PROTECTIONGROUPTRACKSTART);
> 
> ^^^^^^^^ This is the undocumented API which waits for a particular
> response.  It will wait until a message with the header
> MESSAGE_RES_AMF_PROTECTIONGROUPTRACKSTART is received.  Any other
> message it queues for the dispatch function to read the inq.
> 
> 3. Finally have a look at the exec/amf/saAmfDispatch function.
> 
>         saQueueIsEmpty(&amfInstance->inq, &empty);
>         if (empty == 0) {
>             /*
>              * Queue is not empty, read data from queue
>              */
>             saQueueItemGet (&amfInstance->inq, (void *)&queue_msg);
>             msg = *queue_msg;
>             memcpy (&dispatch_data, msg, msg->size);
>             saQueueItemRemove (&amfInstance->inq);
>         } else {
>            /*
>              * Queue empty, read response from socket
>              */
>             error = saRecvRetry (amfInstance->fd, &dispatch_data.header,
>                 sizeof (struct message_header), MSG_WAITALL |
> MSG_NOSIGNAL);
>             if (error != SA_OK) {
>                 goto error_unlock;
>             }
>             if (dispatch_data.header.size > sizeof (struct
> message_header)) {
>                 error = saRecvRetry (amfInstance->fd,
> &dispatch_data.data,
>                     dispatch_data.header.size - sizeof (struct
> message_header),
>                     MSG_WAITALL | MSG_NOSIGNAL);
>                 if (error != SA_OK) {
>                     goto error_unlock;
>                 }
>             }
>         }
> 
> This code basically checks if the queue is empty, then reads from the
> queue if there is a request, otherwise it reads from the socket.

OK, I think that looks like what I want to do.  I'll go through the code
and make sure.

> 
> You might ask why doesn't the poll (not shown) block if there are
> messages in the queue but none in the socket.  It doesn't block because
> every time a saRecvQueue queues a message, it sends a request to the
> executive (activate poll) which then sends a dummy message back to the
> library (activate poll) which keeps poll from blocking.  The dummy
> message is ignored by the dispatch function.  
> 
> Not a great approach (the activate poll stuff).  I have an idea to fix
> it though.  Before a poll is ever done, the inq could be checked to see
> if it is empty.  If there are messages on the inq, the dispatch function
> would not call poll, but instead indicate to the dispatch function to
> dispatch messages.
> 
> Fortunately most of this activate poll mess is hidden from the library
> developer in saRecvQueue (this does the activate poll stuff).  The
> develoepr simply has to be aware that the activate poll message is
> coming and ignore it appropriately.

Thank you,
Mark.

> 
> Thanks!
> -steve
-- 
Mark Haverkamp <markh at osdl.org>




More information about the Openais mailing list