LTKCPP-- LLRP Toolkit C Plus Plus Library
ltkcpp_connection.cpp
Go to the documentation of this file.
1 
2 /*
3  *****************************************************************************
4  * *
5  * IMPINJ CONFIDENTIAL AND PROPRIETARY *
6  * *
7  * This source code is the sole property of Impinj, Inc. Reproduction or *
8  * utilization of this source code in whole or in part is forbidden without *
9  * the prior written consent of Impinj, Inc. *
10  * *
11  * (c) Copyright Impinj, Inc. 2007,2008. All rights reserved. *
12  * *
13  *****************************************************************************/
14 
31 #include <assert.h>
32 
33 #ifdef _WIN32
34 #include <Ws2tcpip.h>
35 #define LLRPCLOSESOCKET(X) closesocket(X)
36 #else
37 #include <unistd.h>
38 #include <sys/types.h>
39 #include <sys/socket.h>
40 #include <netdb.h>
41 #define LLRPCLOSESOCKET(X) close(X)
42 #endif
43 
44 #include <openssl/ssl.h>
45 
46 #include "ltkcpp_platform.h"
47 #include "ltkcpp_base.h"
48 #include "ltkcpp_frame.h"
49 #include "ltkcpp_connection.h"
50 
51 #define LLRP1_TCP_PORT "5084"
52 #define LLRP1_TLS_PORT "5085"
53 
54 // Windows defines INVALID_SOCKET the following way, and we must define it the same
55 // way on Linux:
56 #ifndef INVALID_SOCKET
57 #define INVALID_SOCKET (unsigned long)(~0)
58 #endif // INVALID_SOCKET
59 
60 // Windows defines SOCKET_ERROR the following way, and we must define it the same
61 // way on Linux:
62 #ifndef SOCKET_ERROR
63 #define SOCKET_ERROR (-1)
64 #endif
65 
66 namespace LLRP
67 {
68 
88  const CTypeRegistry * pTypeRegistry,
89  unsigned int nBufferSize)
90 {
91  initializeWinsock();
92  initializeOpenSSL();
93 
94  /*
95  * Apply default buffer size
96  */
97  if(0 == nBufferSize)
98  {
99  nBufferSize = 128u*1024u;
100  }
101 
102  /*
103  * Make sure the buffer size is sane. This is arbitrary.
104  * The smallest message is 10 bytes, but it ain't anything
105  * useful. 1024u covers a surprising number of messages.
106  */
107  if(1024u > nBufferSize || 1u*1024u*1024u < nBufferSize)
108  {
109  throw "Insane buffer size";
110  }
111 
112  /*
113  * Capture variables. A NULL m_pBio indicates there
114  * is no connection yet.
115  */
116  m_pBio = NULL;
117  m_pTypeRegistry = pTypeRegistry;
118  m_nBufferSize = nBufferSize;
119 
120  memset(&m_Recv, 0, sizeof m_Recv);
121  memset(&m_Send, 0, sizeof m_Send);
122 
123  /*
124  * Allocate and check each the recv and send buffers.
125  */
126  m_Recv.pBuffer = new llrp_byte_t[nBufferSize];
127  m_Send.pBuffer = new llrp_byte_t[nBufferSize];
128 
129  /*
130  * Zero-fill buffers just so debugger printing is tidy
131  */
132  memset(m_Recv.pBuffer, 0, nBufferSize);
133  memset(m_Send.pBuffer, 0, nBufferSize);
134 }
135 
136 
145 {
146  /*
147  * Close the connection, if one
148  */
150 
151  /*
152  * Destruct any messages on the input queue
153  */
154  for (
155  std::list<CMessage *>::iterator msg = m_listInputQueue.begin();
156  msg != m_listInputQueue.end();
157  msg++)
158  {
159  delete *msg;
160  }
161 
162  /*
163  * free each the receive and send bufers
164  */
165  delete[] m_Recv.pBuffer;
166  delete[] m_Send.pBuffer;
167 
168  shutdownWinsock();
169 }
170 
171 
183 int CConnection::openConnectionToReader(const char * pReaderHostName)
184 {
185  return openConnectionToReader(pReaderHostName, E_LLRP_CONNECTION_TYPE_UNSECURE);
186 }
187 
199 int CConnection::openSecureConnectionToReader(const char * pReaderHostName)
200 {
201  return openConnectionToReader(pReaderHostName, E_LLRP_CONNECTION_TYPE_SSL);
202 }
203 
216 int CConnection::openConnectionToReader(const char * pReaderHostName, E_LLRP_CONNECTION_TYPE eType)
217 {
218  int rc = -1;
219  unsigned long hSocket = INVALID_SOCKET;
220  BIO* pSocketBio = NULL;
221 
222  /*
223  * Clear the connect error string
224  */
225  m_pConnectErrorStr = NULL;
226 
227  /*
228  * Make sure there isn't already a connection.
229  */
230  if(NULL != m_pBio)
231  {
232  m_pConnectErrorStr = "already connected";
233  return -1;
234  }
235 
236  // Open a raw socket to the reader:
237  switch (eType)
238  {
239  case E_LLRP_CONNECTION_TYPE_SSL:
240  rc = openSocketConnection(pReaderHostName, LLRP1_TLS_PORT, &hSocket);
241  break;
242  case E_LLRP_CONNECTION_TYPE_UNSECURE:
243  rc = openSocketConnection(pReaderHostName, LLRP1_TCP_PORT, &hSocket);
244  break;
245  default:
246  m_pConnectErrorStr = "Unknown connection type.";
247  rc = -1;
248  break;
249  }
250 
251  if (rc != 0)
252  {
253  // log message should already be set to the appropriate error
254  // by openSocketConnection
255  return -1;
256  }
257 
258  // Wrap the socket in an OpenSSL 'BIO'
259  pSocketBio = BIO_new_socket(hSocket, BIO_CLOSE);
260  if (pSocketBio == NULL)
261  {
262  m_pConnectErrorStr = "Failed to register socket with OpenSSL.";
263  LLRPCLOSESOCKET(hSocket);
264 
265  return -1;
266  }
267 
268  // If we're performing a secured connection, we'll need to create an SSL
269  // 'BIO' and push that onto the BIO chain.
270  if (eType == E_LLRP_CONNECTION_TYPE_SSL)
271  {
272  BIO* pSslBio = NULL;
273  int rc = initializeSslBio(&pSslBio);
274  if (rc != 0)
275  {
276  BIO_free_all(pSocketBio);
277  return -1;
278  }
279 
280  BIO_push(pSslBio, pSocketBio);
281 
282  rc = BIO_do_handshake(pSslBio);
283  if (rc == 1)
284  {
285  this->m_pBio = pSslBio;
286  }
287  else
288  {
289  m_pConnectErrorStr = "Failed to perform TLS handshake";
290  BIO_free_all(pSslBio);
291  return -1;
292  }
293  }
294  else
295  {
296  this->m_pBio = pSocketBio;
297  }
298 
299  return 0;
300 }
301 
315 int CConnection::openSocketConnection(const char* pkzReaderHostName, const char* pkzPort, unsigned long* phSocket)
316 {
317  if (phSocket == NULL)
318  {
319  m_pConnectErrorStr = "Internal error.";
320  return -1;
321  }
322 
323  addrinfo* pAddrInfo = NULL;
324  int rc = getaddrinfo(pkzReaderHostName, pkzPort, NULL, &pAddrInfo);
325  if (rc != 0)
326  {
327  m_pConnectErrorStr = "Failed to resolve host.";
328  freeaddrinfo(pAddrInfo);
329  return -1;
330  }
331 
332  unsigned long hSocket = socket(pAddrInfo->ai_family, SOCK_STREAM, IPPROTO_TCP);
333  if (hSocket == INVALID_SOCKET)
334  {
335  m_pConnectErrorStr = "Failed to allocate a socket descriptor.";
336  freeaddrinfo(pAddrInfo);
337  return -1;
338  }
339 
340  rc = connect(hSocket, pAddrInfo->ai_addr, pAddrInfo->ai_addrlen);
341  if (rc == SOCKET_ERROR)
342  {
343  m_pConnectErrorStr = "Failed to connect to host.";
344  freeaddrinfo(pAddrInfo);
345  return -1;
346  }
347 
348  *phSocket = hSocket;
349  freeaddrinfo(pAddrInfo);
350 
351  return rc;
352 }
353 
365 int CConnection::initializeSslBio(BIO** ppBio)
366 {
367  BIO* pBio = NULL;
368  long sslOptions = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3;
369 
370  if (ppBio == NULL)
371  {
372  m_pConnectErrorStr = "Internal parameter failure";
373  return -1;
374  }
375 
376  SSL_CTX* pSslCtx = SSL_CTX_new(SSLv23_method());
377  if (pSslCtx == NULL)
378  {
379  m_pConnectErrorStr = "System SSL context failure";
380  return -1;
381  }
382 
383  SSL_CTX_set_verify(pSslCtx, SSL_VERIFY_NONE, NULL);
384  SSL_CTX_set_options(pSslCtx, sslOptions);
385 
386  pBio = BIO_new_ssl(pSslCtx, 1); // If "client" is non-zero, the SSL bio is initialized in client mode.
387  SSL_CTX_free(pSslCtx);
388  if (pBio == NULL)
389  {
390  m_pConnectErrorStr = "System SSL socket allocation failure";
391  return -1;
392  }
393 
394  *ppBio = pBio;
395  return 0;
396 }
397 
408 const char *
410 {
411  return m_pConnectErrorStr;
412 }
413 
414 
425 int
427 {
428  SSL* pSsl = NULL;
429  int rc = -1;
430 
431  if(NULL == m_pBio)
432  {
433  m_pConnectErrorStr = "not connected";
434  return -1;
435  }
436 
437  BIO_get_ssl(m_pBio, pSsl);
438  if (pSsl != NULL)
439  {
440  BIO_ssl_shutdown(m_pBio);
441  }
442 
443  BIO_free_all(m_pBio);
444  m_pBio = NULL;
445 
446  rc = shutdownWinsock();
447  return rc;
448 }
449 
450 
473 CMessage *
475  CMessage * pSendMessage,
476  int nMaxMS)
477 {
478  const CTypeDescriptor * pResponseType;
479  EResultCode lrc;
480  CMessage * pResponseMessage;
481 
482  /*
483  * Determine the response type. The type descriptor
484  * of the outgoing request message points to the
485  * type descriptor of the response. Since we are
486  * totally dependent upon it, fail if there
487  * is no response type pointer value.
488  */
489  pResponseType = pSendMessage->m_pType->m_pResponseType;
490  if(NULL == pResponseType)
491  {
492  CErrorDetails * pError = &m_Send.ErrorDetails;
493 
494  pError->clear();
496  "send message has no response type");
497  return NULL;
498  }
499 
500  /*
501  * Send the request
502  */
503  lrc = sendMessage(pSendMessage);
504  if(RC_OK != lrc)
505  {
506  return NULL;
507  }
508 
509  /*
510  * Receive the response subject to timeout
511  */
512  pResponseMessage = recvResponse(nMaxMS,
513  pResponseType, pSendMessage->getMessageID());
514 
515  /*
516  * Whatever recvResponse() returned is the result.
517  */
518  return pResponseMessage;
519 }
520 
521 
536 const CErrorDetails *
538 {
539  const CErrorDetails * pError;
540 
541  pError = getSendError();
542  if(RC_OK == pError->m_eResultCode)
543  {
544  pError = getRecvError();
545  }
546 
547  return pError;
548 }
549 
550 
568  CMessage * pMessage)
569 {
570  CErrorDetails * pError = &m_Send.ErrorDetails;
571  CFrameEncoder frameEncoder(m_Send.pBuffer, m_nBufferSize);
572 
573  /*
574  * Clear the error details in the send state.
575  */
576  pError->clear();
577 
578  /*
579  * Make sure the socket is open.
580  */
581  if(NULL == m_pBio)
582  {
583  pError->resultCodeAndWhatStr(RC_MiscError, "not connected");
584  return pError->m_eResultCode;
585  }
586 
587  /*
588  * Encode the message, then check the encoder's ErrorDetails for results.
589  */
590  frameEncoder.encodeElement(pMessage);
591 
592  /*
593  * Regardless of what happened capture the error details
594  * and the number of bytes placed in the buffer.
595  */
596  m_Send.ErrorDetails = frameEncoder.m_ErrorDetails;
597  m_Send.nBuffer = frameEncoder.getLength();
598 
599  /*
600  * If the encoding appears complete write the frame
601  * to the connection. NB: this is not ready for
602  * non-blocking I/O (EWOULDBLOCK).
603  */
604  if (RC_OK == pError->m_eResultCode)
605  {
606  int rc = BIO_write(m_pBio, m_Send.pBuffer, (m_Send.nBuffer * sizeof(llrp_byte_t)));
607  if(rc != (int)m_Send.nBuffer)
608  {
609  /* Yikes! */
610  pError->resultCodeAndWhatStr(RC_SendIOError, "send IO error");
611  }
612  }
613 
614  /*
615  * Done.
616  */
617  return pError->m_eResultCode;
618 }
619 
620 
630 const CErrorDetails *
632 {
633  return &m_Send.ErrorDetails;
634 }
635 
636 
657 CMessage *
659  int nMaxMS)
660 {
661  time_t timeLimit = calculateTimeLimit(nMaxMS);
662  EResultCode lrc;
663  CMessage * pMessage;
664 
665  /*
666  * Make sure the socket is open.
667  */
668  if(NULL == m_pBio)
669  {
670  CErrorDetails * pError = &m_Recv.ErrorDetails;
671 
672  pError->resultCodeAndWhatStr(RC_MiscError, "not connected");
673  return NULL;
674  }
675 
676  /*
677  * Loop until victory or some sort of exception happens
678  */
679  for(;;)
680  {
681  /*
682  * Check the input queue to see if there is already
683  * a message pending.
684  */
685  if(!m_listInputQueue.empty())
686  {
687  pMessage = m_listInputQueue.front();
688  m_listInputQueue.pop_front();
689  return pMessage;
690  }
691 
692  /*
693  * No message available. Advance the receiver state
694  * and see if a message is produced.
695  */
696  lrc = recvAdvance(nMaxMS, timeLimit);
697  if(lrc != RC_OK)
698  {
699  return NULL;
700  }
701  }
702 }
703 
704 
715 const CErrorDetails *
717 {
718  return &m_Recv.ErrorDetails;
719 }
720 
721 
768 CMessage *
770  int nMaxMS,
771  const CTypeDescriptor * pResponseType,
772  llrp_u32_t ResponseMessageID)
773 {
774  time_t timeLimit = calculateTimeLimit(nMaxMS);
775  const CTypeDescriptor * pErrorMsgType;
776  EResultCode lrc;
777  CMessage * pMessage;
778 
779  /*
780  * Make sure the socket is open.
781  */
782  if(NULL == m_pBio)
783  {
784  CErrorDetails * pError = &m_Recv.ErrorDetails;
785 
786  pError->resultCodeAndWhatStr(RC_MiscError, "not connected");
787  return NULL;
788  }
789 
790  /*
791  * Look up the ERROR_MESSAGE type descriptor now.
792  */
793  pErrorMsgType = m_pTypeRegistry->lookupMessage(100u);
794 
795  /*
796  * Loop until victory or some sort of exception happens
797  */
798  for(;;)
799  {
800  /*
801  * Check the input queue to see if the sought
802  * message is present.
803  */
804  for (
805  std::list<CMessage *>::iterator msg = m_listInputQueue.begin();
806  msg != m_listInputQueue.end();
807  msg++)
808  {
809  pMessage = *msg;
810 
811  /*
812  * Are we looking for a particular message type?
813  */
814  if(NULL != pResponseType)
815  {
816  /*
817  * See if it is the sought response type or
818  * an ERROR_MESSAGE.
819  */
820  if(pMessage->m_pType != pResponseType &&
821  pMessage->m_pType != pErrorMsgType)
822  {
823  /* Type does not match. Keep looking. */
824  continue;
825  }
826  }
827 
828  /*
829  * Are we looking for a particular message ID?
830  */
831  if(0 != ResponseMessageID)
832  {
833  if(pMessage->getMessageID() != ResponseMessageID)
834  {
835  /* Message ID does not match. Keep looking. */
836  continue;
837  }
838  }
839 
840  /*
841  * Found it. Unlink it from the queue and return it.
842  */
843  m_listInputQueue.remove(pMessage);
844  return pMessage;
845  }
846 
847  /*
848  * Sought message is not in the queue. Advance the
849  * receiver state and see if the message is produced.
850  */
851  lrc = recvAdvance(nMaxMS, timeLimit);
852  if(lrc != RC_OK)
853  {
854  return NULL;
855  }
856 
857  /*
858  * Loop to the top and try again.
859  */
860  }
861 }
862 
863 
899 CConnection::recvAdvance (
900  int nMaxMS,
901  time_t timeLimit)
902 {
903  CErrorDetails * pError = &m_Recv.ErrorDetails;
904 
905  /*
906  * Clear the error details in the receiver state.
907  */
908  pError->clear();
909 
910  /*
911  * Loop until victory or some sort of exception happens
912  */
913  for(;;)
914  {
915  /*
916  * Note that the frame is in progress.
917  * Existing buffer content, if any, is deemed
918  * invalid or incomplete.
919  */
920  m_Recv.bFrameValid = FALSE;
921 
922  /*
923  * Check to see if we have a frame in the buffer.
924  * If not, how many more bytes do we need?
925  *
926  * LLRP_FrameExtract() status
927  *
928  * FRAME_ERROR Impossible situation, like message
929  * length too small or the like.
930  * Recovery in this situation is
931  * unlikely and probably the app
932  * should drop the connection.
933  *
934  * FRAME_READY Frame is complete. Details are
935  * available for pre-decode decisions.
936  *
937  * FRAME_NEED_MORE Need more input bytes to finish the frame.
938  * The m_nBytesNeeded field is how many more.
939  */
940  m_Recv.FrameExtract = CFrameExtract(m_Recv.pBuffer, m_Recv.nBuffer);
941 
942  /*
943  * Framing error?
944  */
945  if(CFrameExtract::FRAME_ERROR == m_Recv.FrameExtract.m_eStatus)
946  {
948  "framing error in message stream");
949  break;
950  }
951 
952  /*
953  * Need more bytes? extractRc>0 means we do and extractRc is the
954  * number of bytes immediately required.
955  */
956  if(CFrameExtract::NEED_MORE == m_Recv.FrameExtract.m_eStatus)
957  {
958  unsigned int nRead = m_Recv.FrameExtract.m_nBytesNeeded;
959  unsigned char * pBufPos = &m_Recv.pBuffer[m_Recv.nBuffer];
960 
961  /*
962  * Before we do anything that might block,
963  * check to see if the time limit is exceeded.
964  */
965  if(0 != timeLimit)
966  {
967  if(time(NULL) > timeLimit)
968  {
969  // Timeout
971  "timeout");
972  break;
973  }
974  }
975 
976  /*
977  * The frame extractor needs more data, make sure the
978  * frame size fits in the receive buffer.
979  */
980  if(m_Recv.nBuffer + nRead > m_nBufferSize)
981  {
983  "buffer overflow");
984  break;
985  }
986 
987  /*
988  * If this is not a block indefinitely request use select()
989  * to see if there is data in time.
990  */
991  if (nMaxMS >= 0)
992  {
993  fd_set readFdSet = {0};
994  timeval timeout = {0};
995  int bioSocket = -1;
996  SSL* pSsl = NULL;
997 
998  // Check for SSL and error out if it's not null
999  BIO_get_ssl(m_pBio, &pSsl);
1000  if (pSsl != NULL)
1001  {
1002  pError->resultCodeAndWhatStr(RC_RecvIOError, "Non-blocking I/O not supported over secure connections.");
1003  break;
1004  }
1005 
1006  FD_ZERO(&readFdSet);
1007  timeout.tv_sec = nMaxMS / 1000u;
1008  timeout.tv_usec = (nMaxMS % 1000u) * 1000u;
1009 
1010  BIO_get_fd(m_pBio, &bioSocket);
1011  if (bioSocket == -1)
1012  {
1013  pError->resultCodeAndWhatStr(RC_RecvIOError, "failed to retrieve socket's file descriptor");
1014  break;
1015  }
1016 
1017  FD_SET(bioSocket, &readFdSet);
1018 
1019  int rc = select((bioSocket+1), &readFdSet, NULL, NULL, &timeout);
1020  if (0 > rc)
1021  {
1022  /* Error */
1023  pError->resultCodeAndWhatStr(RC_RecvIOError, "poll failed");
1024  break;
1025  }
1026  else if (0 == rc)
1027  {
1028  /* Timeout */
1029  pError->resultCodeAndWhatStr(RC_RecvTimeout, "timeout");
1030  break;
1031  }
1032  }
1033 
1034  /*
1035  * Call BIO_read, and if no data, but should_retry is true, retry within timeout window
1036  */
1037  int rc = BIO_read(m_pBio, pBufPos, nRead);
1038 
1039  // We will retry on the next go around if need be, checking against the timeout, so only break
1040  // if BIO_should_retry returns false.
1041  if ((0 == rc) && (!BIO_should_retry(m_pBio)))
1042  {
1044  "connection closed by remote");
1045  break;
1046  }
1047  else if (0 > rc)
1048  {
1050  "recv IO error");
1051  break;
1052  }
1053  else // We have data!
1054  {
1055  m_Recv.nBuffer += rc;
1056 
1057  // Re-run the loop in order to call CFrameExtract's constructor
1058  // again, which will determine if another network read is
1059  // necessary or if the message is now assembled and ready
1060  // for further consumption.
1061  continue;
1062  }
1063  }
1064 
1065  /*
1066  * Is the frame ready?
1067  * If a valid frame is present, decode and enqueue it.
1068  */
1069  if(CFrameExtract::READY == m_Recv.FrameExtract.m_eStatus)
1070  {
1071  /*
1072  * Frame appears complete. Time to try to decode it.
1073  */
1074  CFrameDecoder decoder(m_pTypeRegistry, m_Recv.pBuffer, m_Recv.nBuffer);
1075  CMessage * pMessage;
1076 
1077  /*
1078  * Now ask the nice, brand new decoder to decode the frame.
1079  * It returns NULL for some kind of error.
1080  */
1081  pMessage = decoder.decodeMessage();
1082 
1083  /*
1084  * Always capture the error details even when it works.
1085  * Whatever happened, we are done with the decoder.
1086  */
1087  m_Recv.ErrorDetails = decoder.m_ErrorDetails;
1088 
1089  /*
1090  * If NULL there was an error. Clean up the
1091  * receive state. Return the error.
1092  */
1093  if(NULL == pMessage)
1094  {
1095  /*
1096  * Make sure the return is not RC_OK
1097  */
1098  if(RC_OK == pError->m_eResultCode)
1099  {
1101  "NULL message but no error");
1102  }
1103 
1104  /*
1105  * All we can do is discard the frame.
1106  */
1107  m_Recv.nBuffer = 0;
1108  m_Recv.bFrameValid = FALSE;
1109 
1110  break;
1111  }
1112 
1113  /*
1114  * Yay! It worked. Enqueue the message.
1115  */
1116  m_listInputQueue.push_back(pMessage);
1117 
1118  /*
1119  * Note that the frame is valid. Consult
1120  * Recv.FrameExtract.m_MessageLength.
1121  * Clear the buffer count to be ready for next time.
1122  */
1123  m_Recv.bFrameValid = TRUE;
1124  m_Recv.nBuffer = 0;
1125 
1126  break;
1127  }
1128 
1129  /*
1130  * If we get here there was an FrameExtract status
1131  * we didn't expect.
1132  */
1133 
1134  /*NOTREACHED*/
1135  assert(0);
1136  }
1137 
1138  return pError->m_eResultCode;
1139 }
1140 
1141 
1164 time_t
1165 CConnection::calculateTimeLimit (
1166  int nMaxMS)
1167 {
1168  if(0 == nMaxMS)
1169  {
1170  /* When just peeking, try for at most one second */
1171  return time(NULL) + 1;
1172  }
1173  else if(0 < nMaxMS)
1174  {
1175  /*
1176  * Try for a at most a certain period of time.
1177  *
1178  * timeLimit = now + ceil(nMaxMS/1000) + 1
1179  *
1180  * The last +1 compensates for not knowing
1181  * when the next time() tick will happen.
1182  *
1183  * For example, if now is SECONDS.999 seconds
1184  * the next tick will happen in 1 millisecond.
1185  * Suppose nMaxMS is 500ms (1/2 second).
1186  * Even rounding 500ms up to 1 second, the
1187  * time limit without the +1 would be
1188  * SECONDS+1 -- 1ms away. That's too soon.
1189  *
1190  * The extra +1 makes the maximum timeout
1191  * longer than required. But the timeLimit
1192  * is a safeguard anyway and usually the
1193  * timeout will occur when the user wants.
1194  */
1195  return time(NULL) + ((nMaxMS + 1999u) / 1000u);
1196  }
1197  else
1198  {
1199  /* Try indefinitely */
1200  return 0;
1201  }
1202 }
1203 
1210 void CConnection::initializeOpenSSL()
1211 {
1212  CRYPTO_malloc_init(); // only needed for windows to safely transfer
1213  // data across the dll boundry as the
1214  // mallocs/heaps are not the same. This is a
1215  // no-op on Linux.
1216 
1217  SSL_library_init(); // SSL_library_init() always returns "1",
1218  // so it is safe to discard the return value.
1219 
1220  SSL_load_error_strings();
1221 }
1222 
1223 
1233 int CConnection::initializeWinsock()
1234 {
1235  int rc = 0;
1236 
1237 #ifdef _WIN32
1238  WSADATA winsockData = { 0 };
1239  rc = WSAStartup(MAKEWORD(2, 2), &winsockData);
1240 #endif
1241 
1242  return rc;
1243 }
1244 
1254 int CConnection::shutdownWinsock()
1255 {
1256  int rc = 0;
1257 
1258 #ifdef _WIN32
1259  rc = WSACleanup();
1260 #endif
1261 
1262  return rc;
1263 }
1264 
1265 }; /* namespace LLRP */
1266 
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.
Definition: ltkcpp_base.h:972
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.
Definition: ltkcpp_base.h:635
Based type descriptions for the LTKCPP library.
Classes to encode and decod LLRP binary frames.
EResultCode
Error result codes for LTK operations.
Definition: ltkcpp_base.h:583
int closeConnectionToReader(void)
Close connection to reader, allow reuse of instance.
A collection of pointers to CTypeDescriptors.
Definition: ltkcpp_base.h:885
const CErrorDetails * getTransactError(void)
Get the details that explains transact() error.
Based types for the LKTCPP library.
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...
Definition: ltkcpp_base.h:776
EResultCode sendMessage(CMessage *pMessage)
Send a LLRP message to a connection.
Class to return error details in LTKCPP operations.
Definition: ltkcpp_base.h:631
llrp_u32_t getMessageID(void) const
Gets the current LLRP Message ID for the Message.
Definition: ltkcpp_base.h:1107
Base Class for All LLRP LTK Messages.
Definition: ltkcpp_base.h:1088
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.
Definition: ltkcpp_base.h:755
const CErrorDetails * getSendError(void)
Get the details that explains sendMessage() error.