32 #include <openssl/ssl.h>
39 #define LLRP1_TCP_PORT (5084u)
40 #define LLRP1_TLS_PORT (5085u)
65 unsigned int nBufferSize)
74 nBufferSize = 128u*1024u;
82 if(1024u > nBufferSize || 1u*1024u*1024u < nBufferSize)
84 throw "Insane buffer size";
92 m_pTypeRegistry = pTypeRegistry;
93 m_nBufferSize = nBufferSize;
95 memset(&m_Recv, 0,
sizeof m_Recv);
96 memset(&m_Send, 0,
sizeof m_Send);
101 m_Recv.pBuffer =
new llrp_byte_t[nBufferSize];
102 m_Send.pBuffer =
new llrp_byte_t[nBufferSize];
107 memset(m_Recv.pBuffer, 0, nBufferSize);
108 memset(m_Send.pBuffer, 0, nBufferSize);
130 std::list<CMessage *>::iterator msg = m_listInputQueue.begin();
131 msg != m_listInputQueue.end();
140 delete[] m_Recv.pBuffer;
141 delete[] m_Send.pBuffer;
199 m_pConnectErrorStr = NULL;
206 m_pConnectErrorStr =
"already connected";
212 case E_LLRP_CONNECTION_TYPE_SSL:
213 rc = initializeSslBio(&pBio);
214 port = LLRP1_TLS_PORT;
216 case E_LLRP_CONNECTION_TYPE_UNSECURE:
218 rc = initializeSocketBio(&pBio);
219 port = LLRP1_TCP_PORT;
229 rc = BIO_set_conn_hostname(pBio, pReaderHostName);
232 m_pConnectErrorStr =
"Unable to assign hostname to socket";
236 rc = BIO_set_conn_int_port(pBio, &port);
239 m_pConnectErrorStr =
"Unable to assign port to socket";
243 rc = BIO_do_connect(pBio);
246 m_pConnectErrorStr =
"Failed to connect to the host";
250 if (eType == E_LLRP_CONNECTION_TYPE_SSL)
252 rc = BIO_do_handshake(pBio);
255 m_pConnectErrorStr =
"Failed to perform TLS handshake";
278 int CConnection::initializeSslBio(BIO** ppBio)
281 long sslOptions = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3;
285 m_pConnectErrorStr =
"Internal parameter failure";
289 const SSL_METHOD* sslMethod = SSLv23_method();
290 if (sslMethod == NULL)
292 m_pConnectErrorStr =
"System SSL socket method failure";
296 SSL_CTX* pSslCtx = SSL_CTX_new(sslMethod);
299 m_pConnectErrorStr =
"System SSL socket context failure";
303 SSL_CTX_set_verify(pSslCtx, SSL_VERIFY_NONE, NULL);
304 SSL_CTX_set_options(pSslCtx, sslOptions);
306 pBio = BIO_new_ssl_connect(pSslCtx);
307 SSL_CTX_free(pSslCtx);
310 m_pConnectErrorStr =
"System SSL socket allocation failure";
329 int CConnection::initializeSocketBio(bio_st** ppBio)
332 BIO_METHOD* pBioMethod = NULL;
336 m_pConnectErrorStr =
"Internal parameter failure";
340 pBioMethod = BIO_s_connect();
341 if (pBioMethod == NULL)
343 m_pConnectErrorStr =
"System socket method failure";
347 pBio = BIO_new(pBioMethod);
350 m_pConnectErrorStr =
"System socket allocation failure";
371 return m_pConnectErrorStr;
390 m_pConnectErrorStr =
"not connected";
394 BIO_free_all(m_pBio);
440 if(NULL == pResponseType)
446 "send message has no response type");
468 return pResponseMessage;
521 CFrameEncoder frameEncoder(m_Send.pBuffer, m_nBufferSize);
540 frameEncoder.encodeElement(pMessage);
546 m_Send.ErrorDetails = frameEncoder.m_ErrorDetails;
547 m_Send.nBuffer = frameEncoder.getLength();
556 int rc = BIO_write(m_pBio, m_Send.pBuffer, (m_Send.nBuffer *
sizeof(llrp_byte_t)));
557 if(rc != (
int)m_Send.nBuffer)
583 return &m_Send.ErrorDetails;
611 time_t timeLimit = calculateTimeLimit(nMaxMS);
635 if(!m_listInputQueue.empty())
637 pMessage = m_listInputQueue.front();
638 m_listInputQueue.pop_front();
646 lrc = recvAdvance(nMaxMS, timeLimit);
668 return &m_Recv.ErrorDetails;
722 llrp_u32_t ResponseMessageID)
724 time_t timeLimit = calculateTimeLimit(nMaxMS);
755 std::list<CMessage *>::iterator msg = m_listInputQueue.begin();
756 msg != m_listInputQueue.end();
764 if(NULL != pResponseType)
770 if(pMessage->
m_pType != pResponseType &&
771 pMessage->
m_pType != pErrorMsgType)
781 if(0 != ResponseMessageID)
793 m_listInputQueue.remove(pMessage);
801 lrc = recvAdvance(nMaxMS, timeLimit);
849 CConnection::recvAdvance (
870 m_Recv.bFrameValid = FALSE;
890 m_Recv.FrameExtract = CFrameExtract(m_Recv.pBuffer, m_Recv.nBuffer);
895 if(CFrameExtract::FRAME_ERROR == m_Recv.FrameExtract.m_eStatus)
898 "framing error in message stream");
906 if(CFrameExtract::NEED_MORE == m_Recv.FrameExtract.m_eStatus)
908 unsigned int nRead = m_Recv.FrameExtract.m_nBytesNeeded;
909 unsigned char * pBufPos = &m_Recv.pBuffer[m_Recv.nBuffer];
917 if(time(NULL) > timeLimit)
930 if(m_Recv.nBuffer + nRead > m_nBufferSize)
943 fd_set readFdSet = {0};
944 timeval timeout = {0};
949 BIO_get_ssl(m_pBio, &pSsl);
957 timeout.tv_sec = nMaxMS / 1000u;
958 timeout.tv_usec = (nMaxMS % 1000u) * 1000u;
960 BIO_get_fd(m_pBio, &bioSocket);
967 FD_SET(bioSocket, &readFdSet);
969 int rc = select((bioSocket+1), &readFdSet, NULL, NULL, &timeout);
987 int rc = BIO_read(m_pBio, pBufPos, nRead);
991 if ((0 == rc) && (!BIO_should_retry(m_pBio)))
994 "connection closed by remote");
1005 m_Recv.nBuffer += rc;
1019 if(CFrameExtract::READY == m_Recv.FrameExtract.m_eStatus)
1024 CFrameDecoder * pDecoder;
1025 CMessage * pMessage;
1031 pDecoder =
new CFrameDecoder(m_pTypeRegistry,
1032 m_Recv.pBuffer, m_Recv.nBuffer);
1037 if(pDecoder == NULL)
1041 m_Recv.bFrameValid = FALSE;
1043 "decoder constructor failed");
1051 pMessage = pDecoder->decodeMessage();
1057 m_Recv.ErrorDetails = pDecoder->m_ErrorDetails;
1068 if(NULL == pMessage)
1076 "NULL message but no error");
1083 m_Recv.bFrameValid = FALSE;
1091 m_listInputQueue.push_back(pMessage);
1098 m_Recv.bFrameValid = TRUE;
1140 CConnection::calculateTimeLimit (
1146 return time(NULL) + 1;
1170 return time(NULL) + ((nMaxMS + 1999u) / 1000u);
1179 void CConnection::initializeOpenSSL()
1181 CRYPTO_malloc_init();
1189 SSL_load_error_strings();
const CTypeDescriptor * lookupMessage(unsigned int MessageTypeNum) const
Lookup a standard message type descriptor. NULL=>not found.
CMessage * recvResponse(int nMaxMS, const CTypeDescriptor *pResponseType, llrp_u32_t ResponseMessageID)
Receive a specific message from a connection.
const CTypeDescriptor * m_pType
The type descriptor desribing this element.
CConnection(const CTypeRegistry *pTypeRegistry, unsigned int nBufferSize)
Construct a new LLRP connection instance.
Class for handling two-way LLRP message traffic.
EResultCode m_eResultCode
Result code from operation.
Based type descriptions for the LTKCPP library.
Classes to encode and decod LLRP binary frames.
EResultCode
Error result codes for LTK operations.
int closeConnectionToReader(void)
Close connection to reader, allow reuse of instance.
A collection of pointers to CTypeDescriptors.
const CErrorDetails * getTransactError(void)
Get the details that explains transact() error.
void resultCodeAndWhatStr(EResultCode eResultCode, const char *pWhatStr)
Convenience function used by the toolkit to set CErrorDetails result code and pWhatStr.
CMessage * recvMessage(int nMaxMS)
Receive a message from a connection.
CMessage * transact(CMessage *pSendMessage, int nMaxMS)
Transact a LLRP request and response to a connection.
const CErrorDetails * getRecvError(void)
Get the details that explains recvMessage() or recvResponse() error.
void clear(void)
Clears the contents of a CErrorDetails.
int openConnectionToReader(const char *pReaderHostName)
Open a connection to the reader over an unencrypted socket.
const CTypeDescriptor * m_pResponseType
For messages (bIsMessage==TRUE), this is the type descriptor for the corresponding response...
EResultCode sendMessage(CMessage *pMessage)
Send a LLRP message to a connection.
Class to return error details in LTKCPP operations.
llrp_u32_t getMessageID(void) const
Gets the current LLRP Message ID for the Message.
Base Class for All LLRP LTK Messages.
const char * getConnectError(void)
Get the string that explains openReaderConnection() error.
~CConnection(void)
Destruct a LLRP connection instance.
int openSecureConnectionToReader(const char *pReaderHostName)
Open a connection to the reader over an encrypted socket.
Describes a message or parameter type.
const CErrorDetails * getSendError(void)
Get the details that explains sendMessage() error.