35 #define LLRPCLOSESOCKET(X) closesocket(X) 38 #include <sys/types.h> 39 #include <sys/socket.h> 41 #define LLRPCLOSESOCKET(X) close(X) 44 #include <openssl/ssl.h> 51 #define LLRP1_TCP_PORT "5084" 52 #define LLRP1_TLS_PORT "5085" 56 #ifndef INVALID_SOCKET 57 #define INVALID_SOCKET (unsigned long)(~0) 58 #endif // INVALID_SOCKET 63 #define SOCKET_ERROR (-1) 89 unsigned int nBufferSize)
99 nBufferSize = 128u*1024u;
107 if(1024u > nBufferSize || 1u*1024u*1024u < nBufferSize)
109 throw "Insane buffer size";
117 m_pTypeRegistry = pTypeRegistry;
118 m_nBufferSize = nBufferSize;
120 memset(&m_Recv, 0,
sizeof m_Recv);
121 memset(&m_Send, 0,
sizeof m_Send);
126 m_Recv.pBuffer =
new llrp_byte_t[nBufferSize];
127 m_Send.pBuffer =
new llrp_byte_t[nBufferSize];
132 memset(m_Recv.pBuffer, 0, nBufferSize);
133 memset(m_Send.pBuffer, 0, nBufferSize);
155 std::list<CMessage *>::iterator msg = m_listInputQueue.begin();
156 msg != m_listInputQueue.end();
165 delete[] m_Recv.pBuffer;
166 delete[] m_Send.pBuffer;
219 unsigned long hSocket = INVALID_SOCKET;
220 BIO* pSocketBio = NULL;
225 m_pConnectErrorStr = NULL;
232 m_pConnectErrorStr =
"already connected";
239 case E_LLRP_CONNECTION_TYPE_SSL:
240 rc = openSocketConnection(pReaderHostName, LLRP1_TLS_PORT, &hSocket);
242 case E_LLRP_CONNECTION_TYPE_UNSECURE:
243 rc = openSocketConnection(pReaderHostName, LLRP1_TCP_PORT, &hSocket);
246 m_pConnectErrorStr =
"Unknown connection type.";
259 pSocketBio = BIO_new_socket(hSocket, BIO_CLOSE);
260 if (pSocketBio == NULL)
262 m_pConnectErrorStr =
"Failed to register socket with OpenSSL.";
263 LLRPCLOSESOCKET(hSocket);
270 if (eType == E_LLRP_CONNECTION_TYPE_SSL)
273 int rc = initializeSslBio(&pSslBio);
276 BIO_free_all(pSocketBio);
280 BIO_push(pSslBio, pSocketBio);
282 rc = BIO_do_handshake(pSslBio);
285 this->m_pBio = pSslBio;
289 m_pConnectErrorStr =
"Failed to perform TLS handshake";
290 BIO_free_all(pSslBio);
296 this->m_pBio = pSocketBio;
315 int CConnection::openSocketConnection(
const char* pkzReaderHostName,
const char* pkzPort,
unsigned long* phSocket)
317 if (phSocket == NULL)
319 m_pConnectErrorStr =
"Internal error.";
323 addrinfo* pAddrInfo = NULL;
324 int rc = getaddrinfo(pkzReaderHostName, pkzPort, NULL, &pAddrInfo);
327 m_pConnectErrorStr =
"Failed to resolve host.";
328 freeaddrinfo(pAddrInfo);
332 unsigned long hSocket = socket(pAddrInfo->ai_family, SOCK_STREAM, IPPROTO_TCP);
333 if (hSocket == INVALID_SOCKET)
335 m_pConnectErrorStr =
"Failed to allocate a socket descriptor.";
336 freeaddrinfo(pAddrInfo);
340 rc = connect(hSocket, pAddrInfo->ai_addr, pAddrInfo->ai_addrlen);
341 if (rc == SOCKET_ERROR)
343 m_pConnectErrorStr =
"Failed to connect to host.";
344 LLRPCLOSESOCKET(hSocket);
345 freeaddrinfo(pAddrInfo);
350 freeaddrinfo(pAddrInfo);
366 int CConnection::initializeSslBio(BIO** ppBio)
369 long sslOptions = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3;
373 m_pConnectErrorStr =
"Internal parameter failure";
377 SSL_CTX* pSslCtx = SSL_CTX_new(SSLv23_method());
380 m_pConnectErrorStr =
"System SSL context failure";
384 SSL_CTX_set_verify(pSslCtx, SSL_VERIFY_NONE, NULL);
385 SSL_CTX_set_options(pSslCtx, sslOptions);
387 pBio = BIO_new_ssl(pSslCtx, 1);
388 SSL_CTX_free(pSslCtx);
391 m_pConnectErrorStr =
"System SSL socket allocation failure";
412 return m_pConnectErrorStr;
434 m_pConnectErrorStr =
"not connected";
438 BIO_get_ssl(m_pBio, &pSsl);
441 BIO_ssl_shutdown(m_pBio);
444 BIO_free_all(m_pBio);
447 rc = shutdownWinsock();
491 if(NULL == pResponseType)
497 "send message has no response type");
519 return pResponseMessage;
572 CFrameEncoder frameEncoder(m_Send.pBuffer, m_nBufferSize);
591 frameEncoder.encodeElement(pMessage);
597 m_Send.ErrorDetails = frameEncoder.m_ErrorDetails;
598 m_Send.nBuffer = frameEncoder.getLength();
607 int rc = BIO_write(m_pBio, m_Send.pBuffer, (m_Send.nBuffer *
sizeof(llrp_byte_t)));
608 if(rc != (
int)m_Send.nBuffer)
634 return &m_Send.ErrorDetails;
662 time_t timeLimit = calculateTimeLimit(nMaxMS);
686 if(!m_listInputQueue.empty())
688 pMessage = m_listInputQueue.front();
689 m_listInputQueue.pop_front();
697 lrc = recvAdvance(nMaxMS, timeLimit);
719 return &m_Recv.ErrorDetails;
773 llrp_u32_t ResponseMessageID)
775 time_t timeLimit = calculateTimeLimit(nMaxMS);
806 std::list<CMessage *>::iterator msg = m_listInputQueue.begin();
807 msg != m_listInputQueue.end();
815 if(NULL != pResponseType)
821 if(pMessage->
m_pType != pResponseType &&
822 pMessage->
m_pType != pErrorMsgType)
832 if(0 != ResponseMessageID)
844 m_listInputQueue.remove(pMessage);
852 lrc = recvAdvance(nMaxMS, timeLimit);
900 CConnection::recvAdvance (
921 m_Recv.bFrameValid = FALSE;
941 m_Recv.FrameExtract = CFrameExtract(m_Recv.pBuffer, m_Recv.nBuffer);
946 if(CFrameExtract::FRAME_ERROR == m_Recv.FrameExtract.m_eStatus)
949 "framing error in message stream");
957 if(CFrameExtract::NEED_MORE == m_Recv.FrameExtract.m_eStatus)
959 unsigned int nRead = m_Recv.FrameExtract.m_nBytesNeeded;
960 unsigned char * pBufPos = &m_Recv.pBuffer[m_Recv.nBuffer];
968 if(time(NULL) > timeLimit)
981 if(m_Recv.nBuffer + nRead > m_nBufferSize)
994 fd_set readFdSet = {0};
995 timeval timeout = {0};
1000 BIO_get_ssl(m_pBio, &pSsl);
1007 FD_ZERO(&readFdSet);
1008 timeout.tv_sec = nMaxMS / 1000u;
1009 timeout.tv_usec = (nMaxMS % 1000u) * 1000u;
1011 BIO_get_fd(m_pBio, &bioSocket);
1012 if (bioSocket == -1)
1018 FD_SET(bioSocket, &readFdSet);
1020 int rc = select((bioSocket+1), &readFdSet, NULL, NULL, &timeout);
1038 int rc = BIO_read(m_pBio, pBufPos, nRead);
1042 if ((0 == rc) && (!BIO_should_retry(m_pBio)))
1045 "connection closed by remote");
1056 m_Recv.nBuffer += rc;
1070 if(CFrameExtract::READY == m_Recv.FrameExtract.m_eStatus)
1075 CFrameDecoder decoder(m_pTypeRegistry, m_Recv.pBuffer, m_Recv.nBuffer);
1082 pMessage = decoder.decodeMessage();
1088 m_Recv.ErrorDetails = decoder.m_ErrorDetails;
1094 if(NULL == pMessage)
1102 "NULL message but no error");
1109 m_Recv.bFrameValid = FALSE;
1117 m_listInputQueue.push_back(pMessage);
1124 m_Recv.bFrameValid = TRUE;
1166 CConnection::calculateTimeLimit (
1172 return time(NULL) + 1;
1196 return time(NULL) + ((nMaxMS + 1999u) / 1000u);
1211 void CConnection::initializeOpenSSL()
1214 CRYPTO_malloc_init();
1222 SSL_load_error_strings();
1235 int CConnection::initializeWinsock()
1240 WSADATA winsockData = { 0 };
1241 rc = WSAStartup(MAKEWORD(2, 2), &winsockData);
1256 int CConnection::shutdownWinsock()
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.
const CTypeDescriptor * lookupMessage(unsigned int MessageTypeNum) const
Lookup a standard message type descriptor. NULL=>not found.
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.