LTKCPP-- LLRP Toolkit C Plus Plus Library
ltkcpp_connection.cpp
Go to the documentation of this file.
00001 
00002 /*
00003  *****************************************************************************
00004  *                                                                           *
00005  *                 IMPINJ CONFIDENTIAL AND PROPRIETARY                       *
00006  *                                                                           *
00007  * This source code is the sole property of Impinj, Inc.  Reproduction or    *
00008  * utilization of this source code in whole or in part is forbidden without  *
00009  * the prior written consent of Impinj, Inc.                                 *
00010  *                                                                           *
00011  * (c) Copyright Impinj, Inc. 2007,2008. All rights reserved.                *
00012  *                                                                           *
00013  *****************************************************************************/
00014 
00031 #include <assert.h>
00032 
00033 #ifdef _WIN32
00034 #include <Ws2tcpip.h>
00035 #define LLRPCLOSESOCKET(X) closesocket(X)
00036 #else
00037 #include <unistd.h>
00038 #include <sys/types.h>
00039 #include <sys/socket.h>
00040 #include <netdb.h>
00041 #define LLRPCLOSESOCKET(X) close(X)
00042 #endif
00043 
00044 #include <openssl/ssl.h>
00045 
00046 #include "ltkcpp_platform.h"
00047 #include "ltkcpp_base.h"
00048 #include "ltkcpp_frame.h"
00049 #include "ltkcpp_connection.h"
00050 
00051 #define LLRP1_TCP_PORT   "5084"
00052 #define LLRP1_TLS_PORT   "5085"
00053 
00054 // Windows defines INVALID_SOCKET the following way, and we must define it the same
00055 // way on Linux:
00056 #ifndef INVALID_SOCKET
00057 #define INVALID_SOCKET (unsigned long)(~0)
00058 #endif // INVALID_SOCKET
00059 
00060 // Windows defines SOCKET_ERROR the following way, and we must define it the same
00061 // way on Linux:
00062 #ifndef SOCKET_ERROR
00063 #define SOCKET_ERROR (-1)
00064 #endif
00065 
00066 namespace LLRP
00067 {
00068 
00087 CConnection::CConnection (
00088   const CTypeRegistry *         pTypeRegistry,
00089   unsigned int                  nBufferSize)
00090 {
00091     initializeWinsock();
00092     initializeOpenSSL();
00093 
00094     /*
00095      * Apply default buffer size
00096      */
00097     if(0 == nBufferSize)
00098     {
00099         nBufferSize = 128u*1024u;
00100     }
00101 
00102     /*
00103      * Make sure the buffer size is sane. This is arbitrary.
00104      * The smallest message is 10 bytes, but it ain't anything
00105      * useful. 1024u covers a surprising number of messages.
00106      */
00107     if(1024u > nBufferSize || 1u*1024u*1024u < nBufferSize)
00108     {
00109         throw "Insane buffer size";
00110     }
00111 
00112     /*
00113      * Capture variables. A NULL m_pBio indicates there
00114      * is no connection yet.
00115      */
00116     m_pBio = NULL;
00117     m_pTypeRegistry = pTypeRegistry;
00118     m_nBufferSize = nBufferSize;
00119 
00120     memset(&m_Recv, 0, sizeof m_Recv);
00121     memset(&m_Send, 0, sizeof m_Send);
00122 
00123     /*
00124      * Allocate and check each the recv and send buffers.
00125      */
00126     m_Recv.pBuffer = new llrp_byte_t[nBufferSize];
00127     m_Send.pBuffer = new llrp_byte_t[nBufferSize];
00128 
00129     /*
00130      * Zero-fill buffers just so debugger printing is tidy
00131      */
00132     memset(m_Recv.pBuffer, 0, nBufferSize);
00133     memset(m_Send.pBuffer, 0, nBufferSize);
00134 }
00135 
00136 
00144 CConnection::~CConnection (void)
00145 {
00146     /*
00147      * Close the connection, if one
00148      */
00149     closeConnectionToReader();
00150 
00151     /*
00152      * Destruct any messages on the input queue
00153      */
00154     for (
00155         std::list<CMessage *>::iterator msg = m_listInputQueue.begin();
00156         msg != m_listInputQueue.end();
00157         msg++)
00158     {
00159         delete *msg;
00160     }
00161 
00162     /*
00163      * free each the receive and send bufers
00164      */
00165     delete[] m_Recv.pBuffer;
00166     delete[] m_Send.pBuffer;
00167 
00168     shutdownWinsock();
00169 }
00170 
00171 
00183 int CConnection::openConnectionToReader(const char * pReaderHostName)
00184 {
00185     return openConnectionToReader(pReaderHostName, E_LLRP_CONNECTION_TYPE_UNSECURE);
00186 }
00187 
00199 int CConnection::openSecureConnectionToReader(const char * pReaderHostName)
00200 {
00201     return openConnectionToReader(pReaderHostName, E_LLRP_CONNECTION_TYPE_SSL);
00202 }
00203 
00216 int CConnection::openConnectionToReader(const char * pReaderHostName, E_LLRP_CONNECTION_TYPE eType)
00217 {
00218     int rc = -1;
00219     unsigned long hSocket = INVALID_SOCKET;
00220     BIO* pSocketBio = NULL;
00221 
00222     /*
00223      * Clear the connect error string
00224      */
00225     m_pConnectErrorStr = NULL;
00226 
00227     /*
00228      * Make sure there isn't already a connection.
00229      */
00230     if(NULL != m_pBio)
00231     {
00232         m_pConnectErrorStr = "already connected";
00233         return -1;
00234     }
00235 
00236     // Open a raw socket to the reader:
00237     switch (eType)
00238     {
00239         case E_LLRP_CONNECTION_TYPE_SSL:
00240             rc = openSocketConnection(pReaderHostName, LLRP1_TLS_PORT, &hSocket);
00241             break;
00242         case E_LLRP_CONNECTION_TYPE_UNSECURE:
00243             rc = openSocketConnection(pReaderHostName, LLRP1_TCP_PORT, &hSocket);
00244             break;
00245         default:
00246             m_pConnectErrorStr = "Unknown connection type.";
00247             rc = -1;
00248             break;
00249     }
00250 
00251     if (rc != 0)
00252     {
00253         // log message should already be set to the appropriate error
00254         // by openSocketConnection
00255         return -1;
00256     }
00257 
00258     // Wrap the socket in an OpenSSL 'BIO'
00259     pSocketBio = BIO_new_socket(hSocket, BIO_CLOSE);
00260     if (pSocketBio == NULL)
00261     {
00262         m_pConnectErrorStr = "Failed to register socket with OpenSSL.";
00263         LLRPCLOSESOCKET(hSocket);
00264 
00265         return -1;
00266     }
00267 
00268     // If we're performing a secured connection, we'll need to create an SSL
00269     // 'BIO' and push that onto the BIO chain.
00270     if (eType == E_LLRP_CONNECTION_TYPE_SSL)
00271     {
00272         BIO* pSslBio = NULL;
00273         int rc = initializeSslBio(&pSslBio);
00274         if (rc != 0)
00275         {
00276             BIO_free_all(pSocketBio);
00277             return -1;
00278         }
00279 
00280         BIO_push(pSslBio, pSocketBio);
00281 
00282         rc = BIO_do_handshake(pSslBio);
00283         if (rc == 1)
00284         {
00285             this->m_pBio = pSslBio;
00286         }
00287         else
00288         {
00289             m_pConnectErrorStr = "Failed to perform TLS handshake";
00290             BIO_free_all(pSslBio);
00291             return -1;
00292         }
00293     }
00294     else
00295     {
00296         this->m_pBio = pSocketBio;
00297     }
00298 
00299     return 0;
00300 }
00301 
00315 int CConnection::openSocketConnection(const char* pkzReaderHostName, const char* pkzPort, unsigned long* phSocket)
00316 {
00317     if (phSocket == NULL)
00318     {
00319         m_pConnectErrorStr = "Internal error.";
00320         return -1;
00321     }
00322 
00323     addrinfo* pAddrInfo = NULL;
00324     int rc = getaddrinfo(pkzReaderHostName, pkzPort, NULL, &pAddrInfo);
00325     if (rc != 0)
00326     {
00327         m_pConnectErrorStr = "Failed to resolve host.";
00328         freeaddrinfo(pAddrInfo);
00329         return -1;
00330     }
00331 
00332     unsigned long hSocket = socket(pAddrInfo->ai_family, SOCK_STREAM, IPPROTO_TCP);
00333     if (hSocket == INVALID_SOCKET)
00334     {
00335         m_pConnectErrorStr = "Failed to allocate a socket descriptor.";
00336         freeaddrinfo(pAddrInfo);
00337         return -1;
00338     }
00339 
00340     rc = connect(hSocket, pAddrInfo->ai_addr, pAddrInfo->ai_addrlen);
00341     if (rc == SOCKET_ERROR)
00342     {
00343         m_pConnectErrorStr = "Failed to connect to host.";
00344         freeaddrinfo(pAddrInfo);
00345         return -1;
00346     }
00347 
00348     *phSocket = hSocket;
00349     freeaddrinfo(pAddrInfo);
00350 
00351     return rc;
00352 }
00353 
00365 int CConnection::initializeSslBio(BIO** ppBio)
00366 {
00367     BIO* pBio = NULL;
00368     long sslOptions = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3;
00369 
00370     if (ppBio == NULL)
00371     {
00372         m_pConnectErrorStr = "Internal parameter failure";
00373         return -1;
00374     }
00375 
00376     SSL_CTX* pSslCtx = SSL_CTX_new(SSLv23_method());
00377     if (pSslCtx == NULL)
00378     {
00379         m_pConnectErrorStr = "System SSL context failure";
00380         return -1;
00381     }
00382 
00383     SSL_CTX_set_verify(pSslCtx, SSL_VERIFY_NONE, NULL);
00384     SSL_CTX_set_options(pSslCtx, sslOptions);
00385 
00386     pBio = BIO_new_ssl(pSslCtx, 1); // If "client" is non-zero, the SSL bio is initialized in client mode.
00387     SSL_CTX_free(pSslCtx);
00388     if (pBio == NULL)
00389     {
00390         m_pConnectErrorStr = "System SSL socket allocation failure";
00391         return -1;
00392     }
00393 
00394     *ppBio = pBio;
00395     return 0;
00396 }
00397 
00408 const char *
00409 CConnection::getConnectError (void)
00410 {
00411     return m_pConnectErrorStr;
00412 }
00413 
00414 
00425 int
00426 CConnection::closeConnectionToReader (void)
00427 {
00428     SSL* pSsl = NULL;
00429     int rc = -1;
00430 
00431     if(NULL == m_pBio)
00432     {
00433         m_pConnectErrorStr = "not connected";
00434         return -1;
00435     }
00436 
00437     BIO_get_ssl(m_pBio, pSsl);
00438     if (pSsl != NULL)
00439     {
00440         BIO_ssl_shutdown(m_pBio);
00441     }
00442 
00443     BIO_free_all(m_pBio);
00444     m_pBio = NULL;
00445 
00446     rc = shutdownWinsock();
00447     return rc;
00448 }
00449 
00450 
00473 CMessage *
00474 CConnection::transact (
00475   CMessage *                    pSendMessage,
00476   int                           nMaxMS)
00477 {
00478     const CTypeDescriptor *     pResponseType;
00479     EResultCode                 lrc;
00480     CMessage *                  pResponseMessage;
00481 
00482     /*
00483      * Determine the response type. The type descriptor
00484      * of the outgoing request message points to the
00485      * type descriptor of the response. Since we are
00486      * totally dependent upon it, fail if there
00487      * is no response type pointer value.
00488      */
00489     pResponseType = pSendMessage->m_pType->m_pResponseType;
00490     if(NULL == pResponseType)
00491     {
00492         CErrorDetails *         pError = &m_Send.ErrorDetails;
00493 
00494         pError->clear();
00495         pError->resultCodeAndWhatStr(RC_MissingResponseType,
00496             "send message has no response type");
00497         return NULL;
00498     }
00499 
00500     /*
00501      * Send the request
00502      */
00503     lrc = sendMessage(pSendMessage);
00504     if(RC_OK != lrc)
00505     {
00506         return NULL;
00507     }
00508 
00509     /*
00510      * Receive the response subject to timeout
00511      */
00512     pResponseMessage = recvResponse(nMaxMS,
00513                             pResponseType, pSendMessage->getMessageID());
00514 
00515     /*
00516      * Whatever recvResponse() returned is the result.
00517      */
00518     return pResponseMessage;
00519 }
00520 
00521 
00536 const CErrorDetails *
00537 CConnection::getTransactError (void)
00538 {
00539     const CErrorDetails *       pError;
00540 
00541     pError = getSendError();
00542     if(RC_OK == pError->m_eResultCode)
00543     {
00544         pError = getRecvError();
00545     }
00546 
00547     return pError;
00548 }
00549 
00550 
00566 EResultCode
00567 CConnection::sendMessage (
00568   CMessage *                    pMessage)
00569 {
00570     CErrorDetails *             pError = &m_Send.ErrorDetails;
00571     CFrameEncoder               frameEncoder(m_Send.pBuffer, m_nBufferSize);
00572 
00573     /*
00574      * Clear the error details in the send state.
00575      */
00576     pError->clear();
00577 
00578     /*
00579      * Make sure the socket is open.
00580      */
00581     if(NULL == m_pBio)
00582     {
00583         pError->resultCodeAndWhatStr(RC_MiscError, "not connected");
00584         return pError->m_eResultCode;
00585     }
00586 
00587     /*
00588      * Encode the message, then check the encoder's ErrorDetails for results.
00589      */
00590     frameEncoder.encodeElement(pMessage);
00591 
00592     /*
00593      * Regardless of what happened capture the error details
00594      * and the number of bytes placed in the buffer.
00595      */
00596     m_Send.ErrorDetails = frameEncoder.m_ErrorDetails;
00597     m_Send.nBuffer = frameEncoder.getLength();
00598 
00599     /*
00600      * If the encoding appears complete write the frame
00601      * to the connection. NB: this is not ready for
00602      * non-blocking I/O (EWOULDBLOCK).
00603      */
00604     if (RC_OK == pError->m_eResultCode)
00605     {
00606         int rc = BIO_write(m_pBio, m_Send.pBuffer, (m_Send.nBuffer * sizeof(llrp_byte_t)));
00607         if(rc != (int)m_Send.nBuffer)
00608         {
00609             /* Yikes! */
00610             pError->resultCodeAndWhatStr(RC_SendIOError, "send IO error");
00611         }
00612     }
00613 
00614     /*
00615      * Done.
00616      */
00617     return pError->m_eResultCode;
00618 }
00619 
00620 
00630 const CErrorDetails *
00631 CConnection::getSendError (void)
00632 {
00633     return &m_Send.ErrorDetails;
00634 }
00635 
00636 
00657 CMessage *
00658 CConnection::recvMessage (
00659   int                           nMaxMS)
00660 {
00661     time_t                      timeLimit = calculateTimeLimit(nMaxMS);
00662     EResultCode                 lrc;
00663     CMessage *                  pMessage;
00664 
00665     /*
00666      * Make sure the socket is open.
00667      */
00668     if(NULL == m_pBio)
00669     {
00670         CErrorDetails *         pError = &m_Recv.ErrorDetails;
00671 
00672         pError->resultCodeAndWhatStr(RC_MiscError, "not connected");
00673         return NULL;
00674     }
00675 
00676     /*
00677      * Loop until victory or some sort of exception happens
00678      */
00679     for(;;)
00680     {
00681         /*
00682          * Check the input queue to see if there is already
00683          * a message pending.
00684          */
00685         if(!m_listInputQueue.empty())
00686         {
00687             pMessage = m_listInputQueue.front();
00688             m_listInputQueue.pop_front();
00689             return pMessage;
00690         }
00691 
00692         /*
00693          * No message available. Advance the receiver state
00694          * and see if a message is produced.
00695          */
00696         lrc = recvAdvance(nMaxMS, timeLimit);
00697         if(lrc != RC_OK)
00698         {
00699             return NULL;
00700         }
00701     }
00702 }
00703 
00704 
00715 const CErrorDetails *
00716 CConnection::getRecvError (void)
00717 {
00718     return &m_Recv.ErrorDetails;
00719 }
00720 
00721 
00768 CMessage *
00769 CConnection::recvResponse (
00770   int                           nMaxMS,
00771   const CTypeDescriptor *       pResponseType,
00772   llrp_u32_t                    ResponseMessageID)
00773 {
00774     time_t                      timeLimit = calculateTimeLimit(nMaxMS);
00775     const CTypeDescriptor *     pErrorMsgType;
00776     EResultCode                 lrc;
00777     CMessage *                  pMessage;
00778 
00779     /*
00780      * Make sure the socket is open.
00781      */
00782     if(NULL == m_pBio)
00783     {
00784         CErrorDetails *         pError = &m_Recv.ErrorDetails;
00785 
00786         pError->resultCodeAndWhatStr(RC_MiscError, "not connected");
00787         return NULL;
00788     }
00789 
00790     /*
00791      * Look up the ERROR_MESSAGE type descriptor now.
00792      */
00793     pErrorMsgType = m_pTypeRegistry->lookupMessage(100u);
00794 
00795     /*
00796      * Loop until victory or some sort of exception happens
00797      */
00798     for(;;)
00799     {
00800         /*
00801          * Check the input queue to see if the sought
00802          * message is present.
00803          */
00804         for (
00805             std::list<CMessage *>::iterator msg = m_listInputQueue.begin();
00806             msg != m_listInputQueue.end();
00807             msg++)
00808         {
00809             pMessage = *msg;
00810 
00811             /*
00812              * Are we looking for a particular message type?
00813              */
00814             if(NULL != pResponseType)
00815             {
00816                 /*
00817                  * See if it is the sought response type or
00818                  * an ERROR_MESSAGE.
00819                  */
00820                 if(pMessage->m_pType != pResponseType &&
00821                    pMessage->m_pType != pErrorMsgType)
00822                 {
00823                     /* Type does not match. Keep looking. */
00824                     continue;
00825                 }
00826             }
00827 
00828             /*
00829              * Are we looking for a particular message ID?
00830              */
00831             if(0 != ResponseMessageID)
00832             {
00833                 if(pMessage->getMessageID() != ResponseMessageID)
00834                 {
00835                     /* Message ID does not match. Keep looking. */
00836                     continue;
00837                 }
00838             }
00839 
00840             /*
00841              * Found it. Unlink it from the queue and return it.
00842              */
00843             m_listInputQueue.remove(pMessage);
00844             return pMessage;
00845         }
00846 
00847         /*
00848          * Sought message is not in the queue. Advance the
00849          * receiver state and see if the message is produced.
00850          */
00851         lrc = recvAdvance(nMaxMS, timeLimit);
00852         if(lrc != RC_OK)
00853         {
00854             return NULL;
00855         }
00856 
00857         /*
00858          * Loop to the top and try again.
00859          */
00860     }
00861 }
00862 
00863 
00898 EResultCode
00899 CConnection::recvAdvance (
00900   int                           nMaxMS,
00901   time_t                        timeLimit)
00902 {
00903     CErrorDetails *             pError = &m_Recv.ErrorDetails;
00904 
00905     /*
00906      * Clear the error details in the receiver state.
00907      */
00908     pError->clear();
00909 
00910     /*
00911      * Loop until victory or some sort of exception happens
00912      */
00913     for(;;)
00914     {
00915         /*
00916          * Note that the frame is in progress.
00917          * Existing buffer content, if any, is deemed
00918          * invalid or incomplete.
00919          */
00920         m_Recv.bFrameValid = FALSE;
00921 
00922         /*
00923          * Check to see if we have a frame in the buffer.
00924          * If not, how many more bytes do we need?
00925          *
00926          * LLRP_FrameExtract() status
00927          *
00928          * FRAME_ERROR          Impossible situation, like message
00929          *                      length too small or the like.
00930          *                      Recovery in this situation is
00931          *                      unlikely and probably the app
00932          *                      should drop the connection.
00933          *
00934          * FRAME_READY          Frame is complete. Details are
00935          *                      available for pre-decode decisions.
00936          *
00937          * FRAME_NEED_MORE      Need more input bytes to finish the frame.
00938          *                      The m_nBytesNeeded field is how many more.
00939          */
00940         m_Recv.FrameExtract = CFrameExtract(m_Recv.pBuffer, m_Recv.nBuffer);
00941 
00942         /*
00943          * Framing error?
00944          */
00945         if(CFrameExtract::FRAME_ERROR == m_Recv.FrameExtract.m_eStatus)
00946         {
00947             pError->resultCodeAndWhatStr(RC_RecvFramingError,
00948                     "framing error in message stream");
00949             break;
00950         }
00951 
00952         /*
00953          * Need more bytes? extractRc>0 means we do and extractRc is the
00954          * number of bytes immediately required.
00955          */
00956         if(CFrameExtract::NEED_MORE == m_Recv.FrameExtract.m_eStatus)
00957         {
00958             unsigned int        nRead = m_Recv.FrameExtract.m_nBytesNeeded;
00959             unsigned char *     pBufPos = &m_Recv.pBuffer[m_Recv.nBuffer];
00960 
00961             /*
00962              * Before we do anything that might block,
00963              * check to see if the time limit is exceeded.
00964              */
00965             if(0 != timeLimit)
00966             {
00967                 if(time(NULL) > timeLimit)
00968                 {
00969                     // Timeout
00970                     pError->resultCodeAndWhatStr(RC_RecvTimeout,
00971                             "timeout");
00972                     break;
00973                 }
00974             }
00975 
00976             /*
00977              * The frame extractor needs more data, make sure the
00978              * frame size fits in the receive buffer.
00979              */
00980             if(m_Recv.nBuffer + nRead > m_nBufferSize)
00981             {
00982                 pError->resultCodeAndWhatStr(RC_RecvBufferOverflow,
00983                         "buffer overflow");
00984                 break;
00985             }
00986 
00987             /*
00988              * If this is not a block indefinitely request use select()
00989              * to see if there is data in time.
00990              */
00991             if (nMaxMS >= 0)
00992             {
00993                 fd_set readFdSet = {0};
00994                 timeval timeout = {0};
00995                 int bioSocket = -1;
00996                 SSL* pSsl = NULL;
00997 
00998                 // Check for SSL and error out if it's not null
00999                 BIO_get_ssl(m_pBio, &pSsl);
01000                 if (pSsl != NULL)
01001                 {
01002                     pError->resultCodeAndWhatStr(RC_RecvIOError, "Non-blocking I/O not supported over secure connections.");
01003                     break;
01004                 }
01005 
01006                 FD_ZERO(&readFdSet);
01007                 timeout.tv_sec = nMaxMS / 1000u;
01008                 timeout.tv_usec = (nMaxMS % 1000u) * 1000u;
01009 
01010                 BIO_get_fd(m_pBio, &bioSocket);
01011                 if (bioSocket == -1)
01012                 {
01013                     pError->resultCodeAndWhatStr(RC_RecvIOError, "failed to retrieve socket's file descriptor");
01014                     break;                        
01015                 }
01016 
01017                 FD_SET(bioSocket, &readFdSet);
01018 
01019                 int rc = select((bioSocket+1), &readFdSet, NULL, NULL, &timeout);
01020                 if (0 > rc)
01021                 {
01022                     /* Error */
01023                     pError->resultCodeAndWhatStr(RC_RecvIOError, "poll failed");
01024                     break;
01025                 }
01026                 else if (0 == rc)
01027                 {
01028                     /* Timeout */
01029                     pError->resultCodeAndWhatStr(RC_RecvTimeout, "timeout");
01030                     break;
01031                 }
01032             }
01033 
01034             /*
01035              * Call BIO_read, and if no data, but should_retry is true, retry within timeout window 
01036              */
01037             int rc = BIO_read(m_pBio, pBufPos, nRead);
01038 
01039             // We will retry on the next go around if need be, checking against the timeout, so only break
01040             // if BIO_should_retry returns false.
01041             if ((0 == rc) && (!BIO_should_retry(m_pBio)))
01042             {
01043                 pError->resultCodeAndWhatStr(RC_RecvEOF, 
01044                         "connection closed by remote");
01045                 break;
01046             }
01047             else if (0 > rc)
01048             {
01049                 pError->resultCodeAndWhatStr(RC_RecvIOError,
01050                     "recv IO error");
01051                 break;
01052             }
01053             else // We have data!
01054             {
01055                 m_Recv.nBuffer += rc;
01056 
01057                 // Re-run the loop in order to call CFrameExtract's constructor
01058                 // again, which will determine if another network read is
01059                 // necessary or if the message is now assembled and ready
01060                 // for further consumption.
01061                 continue;
01062             }
01063         }
01064 
01065         /*
01066          * Is the frame ready?
01067          * If a valid frame is present, decode and enqueue it.
01068          */
01069         if(CFrameExtract::READY == m_Recv.FrameExtract.m_eStatus)
01070         {
01071             /*
01072              * Frame appears complete. Time to try to decode it.
01073              */
01074             CFrameDecoder decoder(m_pTypeRegistry, m_Recv.pBuffer, m_Recv.nBuffer);
01075             CMessage *          pMessage;
01076 
01077             /*
01078              * Now ask the nice, brand new decoder to decode the frame.
01079              * It returns NULL for some kind of error.
01080              */
01081             pMessage = decoder.decodeMessage();
01082 
01083             /*
01084              * Always capture the error details even when it works.
01085              * Whatever happened, we are done with the decoder.
01086              */
01087             m_Recv.ErrorDetails = decoder.m_ErrorDetails;
01088 
01089             /*
01090              * If NULL there was an error. Clean up the
01091              * receive state. Return the error.
01092              */
01093             if(NULL == pMessage)
01094             {
01095                 /*
01096                  * Make sure the return is not RC_OK
01097                  */
01098                 if(RC_OK == pError->m_eResultCode)
01099                 {
01100                     pError->resultCodeAndWhatStr(RC_MiscError,
01101                             "NULL message but no error");
01102                 }
01103 
01104                 /*
01105                  * All we can do is discard the frame.
01106                  */
01107                 m_Recv.nBuffer = 0;
01108                 m_Recv.bFrameValid = FALSE;
01109 
01110                 break;
01111             }
01112 
01113             /*
01114              * Yay! It worked. Enqueue the message.
01115              */
01116             m_listInputQueue.push_back(pMessage);
01117 
01118             /*
01119              * Note that the frame is valid. Consult
01120              * Recv.FrameExtract.m_MessageLength.
01121              * Clear the buffer count to be ready for next time.
01122              */
01123             m_Recv.bFrameValid = TRUE;
01124             m_Recv.nBuffer = 0;
01125 
01126             break;
01127         }
01128 
01129         /*
01130          * If we get here there was an FrameExtract status
01131          * we didn't expect.
01132          */
01133 
01134         /*NOTREACHED*/
01135         assert(0);
01136     }
01137 
01138     return pError->m_eResultCode;
01139 }
01140 
01141 
01164 time_t
01165 CConnection::calculateTimeLimit (
01166   int                           nMaxMS)
01167 {
01168     if(0 == nMaxMS)
01169     {
01170         /* When just peeking, try for at most one second */
01171         return time(NULL) + 1;
01172     }
01173     else if(0 < nMaxMS)
01174     {
01175         /*
01176          * Try for a at most a certain period of time.
01177          *
01178          * timeLimit = now + ceil(nMaxMS/1000) + 1
01179          *
01180          * The last +1 compensates for not knowing
01181          * when the next time() tick will happen.
01182          *
01183          * For example, if now is SECONDS.999 seconds
01184          * the next tick will happen in 1 millisecond.
01185          * Suppose nMaxMS is 500ms (1/2 second).
01186          * Even rounding 500ms up to 1 second, the
01187          * time limit without the +1 would be
01188          * SECONDS+1 -- 1ms away. That's too soon.
01189          *
01190          * The extra +1 makes the maximum timeout
01191          * longer than required. But the timeLimit
01192          * is a safeguard anyway and usually the
01193          * timeout will occur when the user wants.
01194          */
01195         return time(NULL) + ((nMaxMS + 1999u) / 1000u);
01196     }
01197     else
01198     {
01199         /* Try indefinitely */
01200         return 0;
01201     }
01202 }
01203 
01210 void CConnection::initializeOpenSSL()
01211 {
01212     CRYPTO_malloc_init();       // only needed for windows to safely transfer
01213                                 // data across the dll boundry as the
01214                                 // mallocs/heaps are not the same. This is a
01215                                 // no-op on Linux.
01216 
01217     SSL_library_init();         // SSL_library_init() always returns "1",
01218                                 // so it is safe to discard the return value.
01219 
01220     SSL_load_error_strings();
01221 }
01222 
01223 
01233 int CConnection::initializeWinsock()
01234 {
01235     int rc = 0;
01236 
01237 #ifdef _WIN32
01238     WSADATA winsockData = { 0 };
01239     rc = WSAStartup(MAKEWORD(2, 2), &winsockData);
01240 #endif
01241 
01242     return rc;
01243 }
01244 
01254 int CConnection::shutdownWinsock()
01255 {
01256     int rc = 0;
01257 
01258 #ifdef _WIN32
01259     rc = WSACleanup();
01260 #endif
01261 
01262     return rc;
01263 }
01264 
01265 }; /* namespace LLRP */
01266