ltkc_connection.c
Go to the documentation of this file.
00001 
00002 /*
00003  ***************************************************************************
00004  *  Copyright 2007,2008 Impinj, Inc.
00005  *
00006  *  Licensed under the Apache License, Version 2.0 (the "License");
00007  *  you may not use this file except in compliance with the License.
00008  *  You may obtain a copy of the License at
00009  *
00010  *      http://www.apache.org/licenses/LICENSE-2.0
00011  *
00012  *  Unless required by applicable law or agreed to in writing, software
00013  *  distributed under the License is distributed on an "AS IS" BASIS,
00014  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00015  *  See the License for the specific language governing permissions and
00016  *  limitations under the License.
00017  *
00018  ***************************************************************************
00019  */
00020 
00039 #include <assert.h>
00040 
00041 #include <poll.h>
00042 #include <unistd.h>
00043 #include <errno.h>
00044 #include <sys/types.h>
00045 #include <sys/socket.h>
00046 #include <netinet/in.h>
00047 #include <netinet/tcp.h>
00048 #include <arpa/inet.h>
00049 #include <unistd.h>
00050 #include <netdb.h>
00051 #include <fcntl.h>
00052 #include <time.h>
00053 
00054 #include "ltkc_platform.h"
00055 #include "ltkc_base.h"
00056 #include "ltkc_frame.h"
00057 #include "ltkc_connection.h"
00058 
00059 
00060 #define LLRP1_TCP_PORT   (5084u)
00061 
00062 
00063 /* forward declaration of private routine. */
00064 static LLRP_tResultCode
00065 recvAdvance (
00066   LLRP_tSConnection *           pConn,
00067   int                           nMaxMS,
00068   time_t                        timeLimit);
00069 
00070 static time_t
00071 calculateTimeLimit (
00072   int                           nMaxMS);
00073 
00074 
00075 
00094 LLRP_tSConnection *
00095 LLRP_Conn_construct (
00096   const LLRP_tSTypeRegistry *   pTypeRegistry,
00097   unsigned int                  nBufferSize)
00098 {
00099     LLRP_tSConnection *         pConn;
00100 
00101     /*
00102      * Apply default buffer size
00103      */
00104     if(0 == nBufferSize)
00105     {
00106         nBufferSize = 128u*1024u;
00107     }
00108 
00109     /*
00110      * Make sure the buffer size is sane. This is arbitrary.
00111      * The smallest message is 10 bytes, but it ain't anything
00112      * useful. 1024u covers a surprising number of messages.
00113      */
00114     if(1024u > nBufferSize || 1u*1024u*1024u < nBufferSize)
00115     {
00116         /* Insane buffer size */
00117         return NULL;
00118     }
00119 
00120     /*
00121      * Allocate, check, and zero-fill connection instance.
00122      */
00123     pConn = malloc(sizeof *pConn);
00124     if(NULL == pConn)
00125     {
00126         return pConn;
00127     }
00128     memset(pConn, 0, sizeof *pConn);
00129 
00130     /*
00131      * Capture variables. fd=-1 indicates there
00132      * is no connection yet.
00133      */
00134     pConn->fd = -1;
00135     pConn->pTypeRegistry = pTypeRegistry;
00136     pConn->nBufferSize = nBufferSize;
00137 
00138     /*
00139      * Allocate and check each the recv and send buffers.
00140      */
00141     pConn->Recv.pBuffer = malloc(nBufferSize);
00142     pConn->Send.pBuffer = malloc(nBufferSize);
00143 
00144     if(NULL == pConn->Recv.pBuffer || NULL == pConn->Send.pBuffer)
00145     {
00146         LLRP_Conn_destruct(pConn);
00147         return NULL;
00148     }
00149 
00150     /*
00151      * Zero-fill buffers just so debugger printing is reasonable
00152      */
00153     memset(pConn->Recv.pBuffer, 0, nBufferSize);
00154     memset(pConn->Send.pBuffer, 0, nBufferSize);
00155 
00156     /*
00157      * Victory
00158      */
00159     return pConn;
00160 }
00161 
00162 
00174 void
00175 LLRP_Conn_destruct (
00176   LLRP_tSConnection *           pConn)
00177 {
00178     if(NULL != pConn)
00179     {
00180         /*
00181          * Close the connection, if one
00182          */
00183         LLRP_Conn_closeConnectionToReader(pConn);
00184 
00185         /*
00186          * Destruct any message in the input queue
00187          */
00188         while(NULL != pConn->pInputQueue)
00189         {
00190             LLRP_tSMessage *    pMessage;
00191 
00192             pMessage = pConn->pInputQueue;
00193             pConn->pInputQueue = pMessage->pQueueNext;
00194 
00195             LLRP_Element_destruct((LLRP_tSElement *)pMessage);
00196         }
00197 
00198         /*
00199          * free each the receive and send bufers
00200          */
00201         if(NULL != pConn->Recv.pBuffer)
00202         {
00203             free(pConn->Recv.pBuffer);
00204         }
00205         if(NULL != pConn->Send.pBuffer)
00206         {
00207             free(pConn->Send.pBuffer);
00208         }
00209 
00210         /*
00211          * Wipe it out so any stale uses are likely to crash
00212          * on a NULL pointer.
00213          */
00214         memset(pConn, 0, sizeof *pConn);
00215 
00216         /*
00217          * Finally, free the connection data structure itself.
00218          */
00219         free(pConn);
00220     }
00221 }
00222 
00223 
00244 int
00245 LLRP_Conn_openConnectionToReader (
00246   LLRP_tSConnection *           pConn,
00247   const char *                  pReaderHostName)
00248 {
00249     int                         Sock;
00250     static const struct addrinfo AddrInfoMask =
00251     {
00252         0,
00253         AF_INET,
00254         SOCK_STREAM,
00255         0,
00256         0,
00257         NULL,
00258         NULL,
00259         NULL
00260     };
00261     struct addrinfo *           HostAddress;
00262     int                         Flag;
00263     struct sockaddr_in          Sin;
00264     int                         Rc;
00265 
00266     /*
00267      * Clear the connect error string
00268      */
00269     pConn->pConnectErrorStr = NULL;
00270 
00271     /*
00272      * Make sure there isn't already a connection.
00273      */
00274     if(0 <= pConn->fd)
00275     {
00276         pConn->pConnectErrorStr = "already connected";
00277         return -1;
00278     }
00279 
00280     /*
00281      * Look up host using getaddrinfo().
00282      * Gethostbyname() could be configured a lot of
00283      * different ways. There is /etc/hosts, DNS, NIS, etc, etc.
00284      * Suffice to say it is big, bulky, and susceptible to stall.
00285      */
00286     if(0 != getaddrinfo(pReaderHostName, NULL, &AddrInfoMask, &HostAddress))
00287     {
00288         pConn->pConnectErrorStr = "host lookup failed";
00289         return -1;
00290     }
00291 
00292     /*
00293      * Convert the address to sockaddr_in format
00294      */
00295     memset(&Sin, 0, sizeof Sin);
00296     Sin.sin_family = AF_INET;
00297     Sin.sin_addr = ((struct sockaddr_in *)(HostAddress->ai_addr))->sin_addr;
00298     Sin.sin_port = htons(LLRP1_TCP_PORT);
00299 
00300     /*
00301      * Done withe the host addrinfo
00302      */
00303     freeaddrinfo(HostAddress);
00304 
00305     /*
00306      * Create the socket.
00307      */
00308     Sock = socket(AF_INET, SOCK_STREAM, 0);
00309     if(0 > Sock)
00310     {
00311         pConn->pConnectErrorStr = "socket() failed";
00312         return -3;
00313     }
00314 
00315     /*
00316      * Connect the socket to reader. This can stall.
00317      */
00318     Rc = connect(Sock, (struct sockaddr *)&Sin, sizeof Sin);
00319     if(0 > Rc)
00320     {
00321         /* Connect failed */
00322         pConn->pConnectErrorStr = "connect() failed";
00323         close(pConn->fd);
00324         return -4;
00325     }
00326 
00327     /*
00328      * Best effort to set no delay. If this doesn't work
00329      * (no reason it shouldn't) we do not declare defeat.
00330      */
00331     Flag = 1;
00332     setsockopt(Sock, IPPROTO_TCP, TCP_NODELAY, (void*)&Flag, sizeof Flag);
00333 
00334     /*
00335      * Record the socket in the connection instance
00336      */
00337     pConn->fd = Sock;
00338 
00339     /*
00340      * Victory
00341      */
00342     return 0;
00343 }
00344 
00345 
00359 const char *
00360 LLRP_Conn_getConnectError (
00361   LLRP_tSConnection *           pConn)
00362 {
00363     return pConn->pConnectErrorStr;
00364 }
00365 
00366 
00379 int
00380 LLRP_Conn_closeConnectionToReader (
00381   LLRP_tSConnection *           pConn)
00382 {
00383     if(0 > pConn->fd)
00384     {
00385         pConn->pConnectErrorStr = "not connected";
00386         return -1;
00387     }
00388 
00389     close(pConn->fd);
00390 
00391     pConn->fd = -1;
00392 
00393     return 0;
00394 }
00395 
00396 
00423 LLRP_tSMessage *
00424 LLRP_Conn_transact (
00425   LLRP_tSConnection *           pConn,
00426   LLRP_tSMessage *              pSendMessage,
00427   int                           nMaxMS)
00428 {
00429     const LLRP_tSTypeDescriptor * pResponseType;
00430     LLRP_tResultCode            lrc;
00431     LLRP_tSMessage *            pResponseMessage;
00432 
00433     /*
00434      * Determine the response type. The type descriptor
00435      * of the outgoing request message points to the
00436      * type descriptor of the response. Since we are
00437      * totally dependent upon it, fail if there
00438      * is no response type pointer value.
00439      */
00440     pResponseType = pSendMessage->elementHdr.pType->pResponseType;
00441     if(NULL == pResponseType)
00442     {
00443         LLRP_tSErrorDetails *   pError = &pConn->Send.ErrorDetails;
00444 
00445         LLRP_Error_clear(pError);
00446         LLRP_Error_resultCodeAndWhatStr(pError,
00447                 LLRP_RC_MissingResponseType,
00448                 "send message has no response type");
00449         return NULL;
00450     }
00451 
00452     /*
00453      * Send the request
00454      */
00455     lrc = LLRP_Conn_sendMessage(pConn, pSendMessage);
00456     if(LLRP_RC_OK != lrc)
00457     {
00458         return NULL;
00459     }
00460 
00461     /*
00462      * Receive the response subject to timeout
00463      */
00464     pResponseMessage = LLRP_Conn_recvResponse(pConn,  nMaxMS,
00465                             pResponseType, pSendMessage->MessageID);
00466 
00467     /*
00468      * Whatever recvResponse() returned is the result.
00469      */
00470     return pResponseMessage;
00471 }
00472 
00473 
00489 const LLRP_tSErrorDetails *
00490 LLRP_Conn_getTransactError (
00491   LLRP_tSConnection *           pConn)
00492 {
00493     const LLRP_tSErrorDetails * pError;
00494 
00495     pError = LLRP_Conn_getSendError(pConn);
00496     if(LLRP_RC_OK == pError->eResultCode)
00497     {
00498         pError = LLRP_Conn_getRecvError(pConn);
00499     }
00500 
00501     return pError;
00502 }
00503 
00504 
00521 LLRP_tResultCode
00522 LLRP_Conn_sendMessage (
00523   LLRP_tSConnection *           pConn,
00524   LLRP_tSMessage *              pMessage)
00525 {
00526     LLRP_tSErrorDetails *       pError = &pConn->Send.ErrorDetails;
00527     LLRP_tSFrameEncoder *       pEncoder;
00528 
00529     /*
00530      * Clear the error details in the send state.
00531      */
00532     LLRP_Error_clear(pError);
00533 
00534     /*
00535      * Make sure the socket is open.
00536      */
00537     if(0 > pConn->fd)
00538     {
00539         LLRP_Error_resultCodeAndWhatStr(pError,
00540             LLRP_RC_MiscError, "not connected");
00541         return pError->eResultCode;
00542     }
00543 
00544     /*
00545      * Construct a frame encoder. It needs to know the buffer
00546      * base and maximum size.
00547      */
00548 
00549     pEncoder = LLRP_FrameEncoder_construct(pConn->Send.pBuffer,
00550                                                 pConn->nBufferSize);
00551 
00552     /*
00553      * Check that the encoder actually got created.
00554      */
00555     if(NULL == pEncoder)
00556     {
00557         LLRP_Error_resultCodeAndWhatStr(pError,
00558             LLRP_RC_MiscError, "encoder constructor failed");
00559         return pError->eResultCode;
00560     }
00561 
00562     /*
00563      * Encode the message. Return value is ignored.
00564      * We check the encoder's ErrorDetails for results.
00565      * The &...encoderHdr is in lieu of type casting since
00566      * the generic LLRP_Encoder_encodeElement() takes the
00567      * generic LLRP_tSEncoder.
00568      */
00569     LLRP_Encoder_encodeElement(&pEncoder->encoderHdr, &pMessage->elementHdr);
00570 
00571     /*
00572      * Regardless of what happened capture the error details
00573      * and the number of bytes placed in the buffer.
00574      */
00575     pConn->Send.ErrorDetails = pEncoder->encoderHdr.ErrorDetails;
00576     pConn->Send.nBuffer = pEncoder->iNext;
00577 
00578     /*
00579      * Bye bye li'l encoder.
00580      */
00581     LLRP_Encoder_destruct(&pEncoder->encoderHdr);
00582 
00583     /*
00584      * If the encoding appears complete write the frame
00585      * to the connection. NB: this is not ready for
00586      * non-blocking I/O (EWOULDBLOCK).
00587      */
00588     if(LLRP_RC_OK == pError->eResultCode)
00589     {
00590         int             rc;
00591 
00592         rc = write(pConn->fd, pConn->Send.pBuffer, pConn->Send.nBuffer);
00593         pError->OtherDetail = rc;
00594         if (-1 == rc)
00595         {
00596           pError->tcpErrno = errno;
00597         }
00598         if(rc != pConn->Send.nBuffer)
00599         {
00600             /* Yikes! */
00601             LLRP_Error_resultCodeAndWhatStr(pError,
00602                 LLRP_RC_SendIOError, "send IO error");
00603         }
00604     }
00605 
00606     /*
00607      * Done.
00608      */
00609     return pError->eResultCode;
00610 }
00611 
00612 
00624 extern const LLRP_tSErrorDetails *
00625 LLRP_Conn_getSendError (
00626   LLRP_tSConnection *           pConn)
00627 {
00628     return &pConn->Send.ErrorDetails;
00629 }
00630 
00631 
00653 LLRP_tSMessage *
00654 LLRP_Conn_recvMessage (
00655   LLRP_tSConnection *           pConn,
00656   int                           nMaxMS)
00657 {
00658     time_t                      timeLimit = calculateTimeLimit(nMaxMS);
00659     LLRP_tResultCode            lrc;
00660     LLRP_tSMessage *            pMessage;
00661 
00662     /*
00663      * Make sure the socket is open.
00664      */
00665     if(0 > pConn->fd)
00666     {
00667         LLRP_tSErrorDetails *   pError = &pConn->Recv.ErrorDetails;
00668 
00669         LLRP_Error_resultCodeAndWhatStr(pError,
00670             LLRP_RC_MiscError, "not connected");
00671         return NULL;
00672     }
00673 
00674     /*
00675      * Loop until victory or some sort of exception happens
00676      */
00677     for(;;)
00678     {
00679         /*
00680          * Check the input queue to see if there is already
00681          * a message pending.
00682          */
00683         pMessage = pConn->pInputQueue;
00684         if(NULL != pMessage)
00685         {
00686             pConn->pInputQueue = pMessage->pQueueNext;
00687             return pMessage;
00688         }
00689 
00690         /*
00691          * No message available. Advance the receiver state
00692          * and see if a message is produced.
00693          */
00694         lrc = recvAdvance(pConn, nMaxMS, timeLimit);
00695         if(lrc != LLRP_RC_OK)
00696         {
00697             return NULL;
00698         }
00699     }
00700 }
00701 
00702 
00715 const LLRP_tSErrorDetails *
00716 LLRP_Conn_getRecvError (
00717   LLRP_tSConnection *           pConn)
00718 {
00719     return &pConn->Recv.ErrorDetails;
00720 }
00721 
00722 
00770 LLRP_tSMessage *
00771 LLRP_Conn_recvResponse (
00772   LLRP_tSConnection *           pConn,
00773   int                           nMaxMS,
00774   const LLRP_tSTypeDescriptor * pResponseType,
00775   llrp_u32_t                    ResponseMessageID)
00776 {
00777     time_t                      timeLimit = calculateTimeLimit(nMaxMS);
00778     const LLRP_tSTypeDescriptor *pErrorMsgType;
00779     LLRP_tResultCode            lrc;
00780     LLRP_tSMessage *            pMessage;
00781     LLRP_tSMessage **           ppMessage;
00782 
00783     /*
00784      * Make sure the socket is open.
00785      */
00786     if(0 > pConn->fd)
00787     {
00788         LLRP_tSErrorDetails *   pError = &pConn->Recv.ErrorDetails;
00789 
00790         LLRP_Error_resultCodeAndWhatStr(pError,
00791             LLRP_RC_MiscError, "not connected");
00792         return NULL;
00793     }
00794 
00795     /*
00796      * Look up the ERROR_MESSAGE type descriptor now.
00797      */
00798     pErrorMsgType = LLRP_TypeRegistry_lookupMessage(
00799                     pConn->pTypeRegistry, 100u);
00800 
00801     /*
00802      * Loop until victory or some sort of exception happens
00803      */
00804     for(;;)
00805     {
00806         /*
00807          * Check the input queue to see if the sought
00808          * message is present.
00809          */
00810         for(
00811             ppMessage = &pConn->pInputQueue;
00812             NULL != (pMessage = *ppMessage);
00813             ppMessage = &pMessage->pQueueNext)
00814         {
00815             /*
00816              * Are we looking for a particular message type?
00817              */
00818             if(NULL != pResponseType)
00819             {
00820                 /*
00821                  * See if it is the sought response type or
00822                  * an ERROR_MESSAGE.
00823                  */
00824                 if(pMessage->elementHdr.pType != pResponseType &&
00825                    pMessage->elementHdr.pType != pErrorMsgType)
00826                 {
00827                     /* Type does not match. Keep looking. */
00828                     continue;
00829                 }
00830             }
00831 
00832             /*
00833              * Are we looking for a particular message ID?
00834              */
00835             if(0 != ResponseMessageID)
00836             {
00837                 if(pMessage->MessageID != ResponseMessageID)
00838                 {
00839                     /* Message ID does not match. Keep looking. */
00840                     continue;
00841                 }
00842             }
00843 
00844             /* Found it */
00845             break;
00846         }
00847 
00848         /*
00849          * If we found it unlink it from the queue and return it.
00850          */
00851         if(NULL != pMessage)
00852         {
00853             *ppMessage = pMessage->pQueueNext;
00854             pMessage->pQueueNext = NULL;
00855             return pMessage;
00856         }
00857 
00858         /*
00859          * Sought message is not in the queue. Advance the
00860          * receiver state and see if the message is produced.
00861          */
00862         lrc = recvAdvance(pConn, nMaxMS, timeLimit);
00863         if(lrc != LLRP_RC_OK)
00864         {
00865             return NULL;
00866         }
00867 
00868         /*
00869          * Loop to the top and try again.
00870          */
00871     }
00872 }
00873 
00874 
00899 static LLRP_tResultCode
00900 recvAdvance (
00901   LLRP_tSConnection *           pConn,
00902   int                           nMaxMS,
00903   time_t                        timeLimit)
00904 {
00905     LLRP_tSErrorDetails *       pError = &pConn->Recv.ErrorDetails;
00906 
00907     /*
00908      * Clear the error details in the receiver state.
00909      */
00910     LLRP_Error_clear(pError);
00911 
00912     /*
00913      * Loop until victory or some sort of exception happens
00914      */
00915     for(;;)
00916     {
00917         int                     rc;
00918 
00919         /*
00920          * Note that the frame is in progress.
00921          * Existing buffer content, if any, is deemed
00922          * invalid or incomplete.
00923          */
00924         pConn->Recv.bFrameValid = FALSE;
00925 
00926         /*
00927          * Check to see if we have a frame in the buffer.
00928          * If not, how many more bytes do we need?
00929          *
00930          * LLRP_FrameExtract() status
00931          *
00932          * LLRP_FRAME_ERROR     Impossible situation, like message
00933          *                      length too small or the like.
00934          *                      Recovery in this situation is
00935          *                      unlikely and probably the app
00936          *                      should drop the connection.
00937          *
00938          * LLRP_FRAME_READY     Frame is complete. Details are
00939          *                      available for pre-decode decisions.
00940          *
00941          * LLRP_FRAME_NEED_MORE Need more input bytes to finish the frame.
00942          *                      The nBytesNeeded field is how many more.
00943          */
00944         pConn->Recv.FrameExtract =
00945             LLRP_FrameExtract(pConn->Recv.pBuffer, pConn->Recv.nBuffer);
00946 
00947         /*
00948          * Framing error?
00949          */
00950         if(LLRP_FRAME_ERROR == pConn->Recv.FrameExtract.eStatus)
00951         {
00952             LLRP_Error_resultCodeAndWhatStr(pError,
00953                 LLRP_RC_RecvFramingError, "framing error in message stream");
00954             break;
00955         }
00956 
00957         /*
00958          * Need more bytes? extractRc>0 means we do and extractRc is the
00959          * number of bytes immediately required.
00960          */
00961         if(LLRP_FRAME_NEED_MORE == pConn->Recv.FrameExtract.eStatus)
00962         {
00963             unsigned int        nRead = pConn->Recv.FrameExtract.nBytesNeeded;
00964             unsigned char *     pBufPos =
00965                                   &pConn->Recv.pBuffer[pConn->Recv.nBuffer];
00966 
00967             /*
00968              * Before we do anything that might block,
00969              * check to see if the time limit is exceeded.
00970              */
00971             if(0 != timeLimit)
00972             {
00973                 if(time(NULL) > timeLimit)
00974                 {
00975                     /* Timeout */
00976                     LLRP_Error_resultCodeAndWhatStr(pError,
00977                         LLRP_RC_RecvTimeout, "timeout");
00978                     break;
00979                 }
00980             }
00981 
00982             /*
00983              * If this is not a block indefinitely request use poll()
00984              * to see if there is data in time.
00985              */
00986             if(nMaxMS >= 0)
00987             {
00988                 struct pollfd           pfd;
00989 
00990                 pfd.fd = pConn->fd;
00991                 pfd.events = POLLIN;
00992                 pfd.revents = 0;
00993 
00994                 rc = poll(&pfd, 1, nMaxMS);
00995                 if(0 > rc)
00996                 {
00997                     /* Error */
00998                     LLRP_Error_resultCodeAndWhatStr(pError,
00999                         LLRP_RC_RecvIOError, "poll failed");
01000                     break;
01001                 }
01002                 if(0 == rc)
01003                 {
01004                     /* Timeout */
01005                     LLRP_Error_resultCodeAndWhatStr(pError,
01006                         LLRP_RC_RecvTimeout, "timeout");
01007                     break;
01008                 }
01009             }
01010 
01011             /*
01012              * Read some number of bytes from the socket.
01013              */
01014             rc = read(pConn->fd, pBufPos, nRead);
01015             if(0 > rc)
01016             {
01017                 /*
01018                  * Error. Note this could be EWOULDBLOCK if the
01019                  * file descriptor is using non-blocking I/O.
01020                  * So we return the error but do not tear-up
01021                  * the receiver state.
01022                  */
01023                 LLRP_Error_resultCodeAndWhatStr(pError,
01024                     LLRP_RC_RecvIOError, "recv IO error");
01025                 break;
01026             }
01027 
01028             if(0 == rc)
01029             {
01030                 /* EOF */
01031                 LLRP_Error_resultCodeAndWhatStr(pError,
01032                     LLRP_RC_RecvEOF, "recv end-of-file");
01033                 break;
01034             }
01035 
01036             /*
01037              * When we get here, rc>0 meaning some bytes were read.
01038              * Update the number of bytes present.
01039              * Then loop to the top and retry the FrameExtract().
01040              */
01041             pConn->Recv.nBuffer += rc;
01042 
01043             continue;
01044         }
01045 
01046         /*
01047          * Is the frame ready?
01048          * If a valid frame is present, decode and enqueue it.
01049          */
01050         if(LLRP_FRAME_READY == pConn->Recv.FrameExtract.eStatus)
01051         {
01052             /*
01053              * Frame appears complete. Time to try to decode it.
01054              */
01055             LLRP_tSFrameDecoder *   pDecoder;
01056             LLRP_tSMessage *        pMessage;
01057             LLRP_tSMessage **       ppMessageTail;
01058 
01059             /*
01060              * Construct a new frame decoder. It needs the registry
01061              * to facilitate decoding.
01062              */
01063             pDecoder = LLRP_FrameDecoder_construct(pConn->pTypeRegistry,
01064                     pConn->Recv.pBuffer, pConn->Recv.nBuffer);
01065 
01066             /*
01067              * Make sure we really got one. If not, weird problem.
01068              */
01069             if(pDecoder == NULL)
01070             {
01071                 /* All we can do is discard the frame. */
01072                 pConn->Recv.nBuffer = 0;
01073                 pConn->Recv.bFrameValid = FALSE;
01074                 LLRP_Error_resultCodeAndWhatStr(pError,
01075                     LLRP_RC_MiscError, "decoder constructor failed");
01076                 break;
01077             }
01078 
01079             /*
01080              * Now ask the nice, brand new decoder to decode the frame.
01081              * It returns NULL for some kind of error.
01082              * The &...decoderHdr is in lieu of type casting since
01083              * the generic LLRP_Decoder_decodeMessage() takes the
01084              * generic LLRP_tSDecoder.
01085              */
01086             pMessage = LLRP_Decoder_decodeMessage(&pDecoder->decoderHdr);
01087 
01088             /*
01089              * Always capture the error details even when it works.
01090              * Whatever happened, we are done with the decoder.
01091              */
01092             pConn->Recv.ErrorDetails = pDecoder->decoderHdr.ErrorDetails;
01093 
01094             /*
01095              * Bye bye and thank you li'l decoder.
01096              */
01097             LLRP_Decoder_destruct(&pDecoder->decoderHdr);
01098 
01099             /*
01100              * If NULL there was an error. Clean up the
01101              * receive state. Return the error.
01102              */
01103             if(NULL == pMessage)
01104             {
01105                 /*
01106                  * Make sure the return is not LLRP_RC_OK
01107                  */
01108                 if(LLRP_RC_OK == pError->eResultCode)
01109                 {
01110                     LLRP_Error_resultCodeAndWhatStr(pError,
01111                         LLRP_RC_MiscError, "NULL message but no error");
01112                 }
01113 
01114                 /*
01115                  * All we can do is discard the frame.
01116                  */
01117                 pConn->Recv.nBuffer = 0;
01118                 pConn->Recv.bFrameValid = FALSE;
01119 
01120                 break;
01121             }
01122 
01123             /*
01124              * Yay! It worked. Enqueue the message.
01125              */
01126             ppMessageTail = &pConn->pInputQueue;
01127             while(NULL != *ppMessageTail)
01128             {
01129                 ppMessageTail = &(*ppMessageTail)->pQueueNext;
01130             }
01131 
01132             pMessage->pQueueNext = NULL;
01133             *ppMessageTail = pMessage;
01134 
01135             /*
01136              * Note that the frame is valid. Consult
01137              * Recv.FrameExtract.MessageLength.
01138              * Clear the buffer count to be ready for next time.
01139              */
01140             pConn->Recv.bFrameValid = TRUE;
01141             pConn->Recv.nBuffer = 0;
01142 
01143             break;
01144         }
01145 
01146         /*
01147          * If we get here there was an FrameExtract status
01148          * we didn't expect.
01149          */
01150 
01151         /*NOTREACHED*/
01152         assert(0);
01153     }
01154 
01155     return pError->eResultCode;
01156 }
01157 
01158 
01182 static time_t
01183 calculateTimeLimit (
01184   int                           nMaxMS)
01185 {
01186     if(0 == nMaxMS)
01187     {
01188         /* When just peeking, try for at most one second */
01189         return time(NULL) + 1;
01190     }
01191     else if(0 < nMaxMS)
01192     {
01193         /*
01194          * Try for a at most a certain period of time.
01195          *
01196          * timeLimit = now + ceil(nMaxMS/1000) + 1
01197          *
01198          * The last +1 compensates for not knowing
01199          * when the next time() tick will happen.
01200          *
01201          * For example, if now is SECONDS.999 seconds
01202          * the next tick will happen in 1 millisecond.
01203          * Suppose nMaxMS is 500ms (1/2 second).
01204          * Even rounding 500ms up to 1 second, the
01205          * time limit without the +1 would be
01206          * SECONDS+1 -- 1ms away. That's too soon.
01207          *
01208          * The extra +1 makes the maximum timeout
01209          * longer than required. But the timeLimit
01210          * is a safeguard anyway and usually the
01211          * timeout will occur when the user wants.
01212          */
01213         return time(NULL) + ((nMaxMS + 1999u) / 1000u);
01214     }
01215     else
01216     {
01217         /* Try indefinitely */
01218         return 0;
01219     }
01220 }


thingmagic_rfid
Author(s): Brian Bingham
autogenerated on Thu May 16 2019 03:01:23